Color selection dialog rewrite.
authorOwen Taylor <otaylor@redhat.com>
Wed, 10 May 2000 21:39:03 +0000 (21:39 +0000)
committerOwen Taylor <otaylor@src.gnome.org>
Wed, 10 May 2000 21:39:03 +0000 (21:39 +0000)
Wed May 10 16:38:17 2000  Owen Taylor  <otaylor@redhat.com>

* gtk/Makefile.am docs/Changes-1.4.txt gtk/gtkcolorsel.[ch]
gtk/gtkhsv.[ch]: Color selection dialog rewrite.

(Original triangle color selector from Simon Budig
<Simon.Budig@unix-ag.org>, Cleaned up and rewritten for GTK+ by
from Jonathan, Havoc, and Federico. Merge into GTK+ done by David
Santiago <mrcooger@cyberverse.com>)

* gtk/gtkcolorseldialog.[ch]: Split color selection dialog
out into a separate widget.

* gtk/testgtk.c: Add some checkbuttons for toggling palette
and opacity controls.

Wed May 10 16:08:09 2000  Owen Taylor  <otaylor@redhat.com>

* configure.in (GTK_LIBS_EXTRA): Remove references to gobject that
snuck in prematurely.

19 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
configure.in
docs/Changes-1.4.txt
gtk/Makefile.am
gtk/gtk.h
gtk/gtkcolorsel.c
gtk/gtkcolorsel.h
gtk/gtkcolorseldialog.c [new file with mode: 0644]
gtk/gtkcolorseldialog.h [new file with mode: 0644]
gtk/gtkhsv.c [new file with mode: 0644]
gtk/gtkhsv.h [new file with mode: 0644]
gtk/testgtk.c
tests/testgtk.c

index be555d20f486066695d2678891cb40cfdabb6e1c..38204c8251e7b2182f92f60bab8276e80275a6cd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,23 @@
+Wed May 10 16:38:17 2000  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/Makefile.am docs/Changes-1.4.txt gtk/gtkcolorsel.[ch]
+       gtk/gtkhsv.[ch]: Color selection dialog rewrite.
+       
+       (Original triangle color selector from Simon Budig
+       <Simon.Budig@unix-ag.org>, Cleaned up and rewritten for GTK+ by
+       from Jonathan, Havoc, and Federico. Merge into GTK+ done by David
+       Santiago <mrcooger@cyberverse.com>)
+
+       * gtk/gtkcolorseldialog.[ch]: Split color selection dialog
+       out into a separate widget.
+
+       * gtk/testgtk.c: Add some checkbuttons for toggling palette
+       and opacity controls.
+
 Wed May 10 16:08:09 2000  Owen Taylor  <otaylor@redhat.com>
 
-       * configure.in (GTK_LIBS_EXTRA): Remove gobject that snuck
-       in prematurely.
+       * configure.in (GTK_LIBS_EXTRA): Remove references to gobject that 
+       snuck in prematurely.
 
 2000-05-07  Tor Lillqvist  <tml@iki.fi>
 
index be555d20f486066695d2678891cb40cfdabb6e1c..38204c8251e7b2182f92f60bab8276e80275a6cd 100644 (file)
@@ -1,7 +1,23 @@
+Wed May 10 16:38:17 2000  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/Makefile.am docs/Changes-1.4.txt gtk/gtkcolorsel.[ch]
+       gtk/gtkhsv.[ch]: Color selection dialog rewrite.
+       
+       (Original triangle color selector from Simon Budig
+       <Simon.Budig@unix-ag.org>, Cleaned up and rewritten for GTK+ by
+       from Jonathan, Havoc, and Federico. Merge into GTK+ done by David
+       Santiago <mrcooger@cyberverse.com>)
+
+       * gtk/gtkcolorseldialog.[ch]: Split color selection dialog
+       out into a separate widget.
+
+       * gtk/testgtk.c: Add some checkbuttons for toggling palette
+       and opacity controls.
+
 Wed May 10 16:08:09 2000  Owen Taylor  <otaylor@redhat.com>
 
-       * configure.in (GTK_LIBS_EXTRA): Remove gobject that snuck
-       in prematurely.
+       * configure.in (GTK_LIBS_EXTRA): Remove references to gobject that 
+       snuck in prematurely.
 
 2000-05-07  Tor Lillqvist  <tml@iki.fi>
 
index be555d20f486066695d2678891cb40cfdabb6e1c..38204c8251e7b2182f92f60bab8276e80275a6cd 100644 (file)
@@ -1,7 +1,23 @@
+Wed May 10 16:38:17 2000  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/Makefile.am docs/Changes-1.4.txt gtk/gtkcolorsel.[ch]
+       gtk/gtkhsv.[ch]: Color selection dialog rewrite.
+       
+       (Original triangle color selector from Simon Budig
+       <Simon.Budig@unix-ag.org>, Cleaned up and rewritten for GTK+ by
+       from Jonathan, Havoc, and Federico. Merge into GTK+ done by David
+       Santiago <mrcooger@cyberverse.com>)
+
+       * gtk/gtkcolorseldialog.[ch]: Split color selection dialog
+       out into a separate widget.
+
+       * gtk/testgtk.c: Add some checkbuttons for toggling palette
+       and opacity controls.
+
 Wed May 10 16:08:09 2000  Owen Taylor  <otaylor@redhat.com>
 
-       * configure.in (GTK_LIBS_EXTRA): Remove gobject that snuck
-       in prematurely.
+       * configure.in (GTK_LIBS_EXTRA): Remove references to gobject that 
+       snuck in prematurely.
 
 2000-05-07  Tor Lillqvist  <tml@iki.fi>
 
index be555d20f486066695d2678891cb40cfdabb6e1c..38204c8251e7b2182f92f60bab8276e80275a6cd 100644 (file)
@@ -1,7 +1,23 @@
+Wed May 10 16:38:17 2000  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/Makefile.am docs/Changes-1.4.txt gtk/gtkcolorsel.[ch]
+       gtk/gtkhsv.[ch]: Color selection dialog rewrite.
+       
+       (Original triangle color selector from Simon Budig
+       <Simon.Budig@unix-ag.org>, Cleaned up and rewritten for GTK+ by
+       from Jonathan, Havoc, and Federico. Merge into GTK+ done by David
+       Santiago <mrcooger@cyberverse.com>)
+
+       * gtk/gtkcolorseldialog.[ch]: Split color selection dialog
+       out into a separate widget.
+
+       * gtk/testgtk.c: Add some checkbuttons for toggling palette
+       and opacity controls.
+
 Wed May 10 16:08:09 2000  Owen Taylor  <otaylor@redhat.com>
 
-       * configure.in (GTK_LIBS_EXTRA): Remove gobject that snuck
-       in prematurely.
+       * configure.in (GTK_LIBS_EXTRA): Remove references to gobject that 
+       snuck in prematurely.
 
 2000-05-07  Tor Lillqvist  <tml@iki.fi>
 
index be555d20f486066695d2678891cb40cfdabb6e1c..38204c8251e7b2182f92f60bab8276e80275a6cd 100644 (file)
@@ -1,7 +1,23 @@
+Wed May 10 16:38:17 2000  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/Makefile.am docs/Changes-1.4.txt gtk/gtkcolorsel.[ch]
+       gtk/gtkhsv.[ch]: Color selection dialog rewrite.
+       
+       (Original triangle color selector from Simon Budig
+       <Simon.Budig@unix-ag.org>, Cleaned up and rewritten for GTK+ by
+       from Jonathan, Havoc, and Federico. Merge into GTK+ done by David
+       Santiago <mrcooger@cyberverse.com>)
+
+       * gtk/gtkcolorseldialog.[ch]: Split color selection dialog
+       out into a separate widget.
+
+       * gtk/testgtk.c: Add some checkbuttons for toggling palette
+       and opacity controls.
+
 Wed May 10 16:08:09 2000  Owen Taylor  <otaylor@redhat.com>
 
-       * configure.in (GTK_LIBS_EXTRA): Remove gobject that snuck
-       in prematurely.
+       * configure.in (GTK_LIBS_EXTRA): Remove references to gobject that 
+       snuck in prematurely.
 
 2000-05-07  Tor Lillqvist  <tml@iki.fi>
 
index be555d20f486066695d2678891cb40cfdabb6e1c..38204c8251e7b2182f92f60bab8276e80275a6cd 100644 (file)
@@ -1,7 +1,23 @@
+Wed May 10 16:38:17 2000  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/Makefile.am docs/Changes-1.4.txt gtk/gtkcolorsel.[ch]
+       gtk/gtkhsv.[ch]: Color selection dialog rewrite.
+       
+       (Original triangle color selector from Simon Budig
+       <Simon.Budig@unix-ag.org>, Cleaned up and rewritten for GTK+ by
+       from Jonathan, Havoc, and Federico. Merge into GTK+ done by David
+       Santiago <mrcooger@cyberverse.com>)
+
+       * gtk/gtkcolorseldialog.[ch]: Split color selection dialog
+       out into a separate widget.
+
+       * gtk/testgtk.c: Add some checkbuttons for toggling palette
+       and opacity controls.
+
 Wed May 10 16:08:09 2000  Owen Taylor  <otaylor@redhat.com>
 
-       * configure.in (GTK_LIBS_EXTRA): Remove gobject that snuck
-       in prematurely.
+       * configure.in (GTK_LIBS_EXTRA): Remove references to gobject that 
+       snuck in prematurely.
 
 2000-05-07  Tor Lillqvist  <tml@iki.fi>
 
index be555d20f486066695d2678891cb40cfdabb6e1c..38204c8251e7b2182f92f60bab8276e80275a6cd 100644 (file)
@@ -1,7 +1,23 @@
+Wed May 10 16:38:17 2000  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/Makefile.am docs/Changes-1.4.txt gtk/gtkcolorsel.[ch]
+       gtk/gtkhsv.[ch]: Color selection dialog rewrite.
+       
+       (Original triangle color selector from Simon Budig
+       <Simon.Budig@unix-ag.org>, Cleaned up and rewritten for GTK+ by
+       from Jonathan, Havoc, and Federico. Merge into GTK+ done by David
+       Santiago <mrcooger@cyberverse.com>)
+
+       * gtk/gtkcolorseldialog.[ch]: Split color selection dialog
+       out into a separate widget.
+
+       * gtk/testgtk.c: Add some checkbuttons for toggling palette
+       and opacity controls.
+
 Wed May 10 16:08:09 2000  Owen Taylor  <otaylor@redhat.com>
 
-       * configure.in (GTK_LIBS_EXTRA): Remove gobject that snuck
-       in prematurely.
+       * configure.in (GTK_LIBS_EXTRA): Remove references to gobject that 
+       snuck in prematurely.
 
 2000-05-07  Tor Lillqvist  <tml@iki.fi>
 
index 0f2f45e39df98e4c6a71218bfaed5213bda50435..da5127cad47e6a88f4bd6ed3164d62bd01d1017f 100644 (file)
@@ -259,9 +259,9 @@ if test x$with_glib = x ; then
     gmodule gthread)
 
   # we do not want to make all gtk progs to link to thread libraries.
-  glib_cflags=`$GLIB_CONFIG glib gobject gmodule --cflags`
+  glib_cflags=`$GLIB_CONFIG glib gmodule --cflags`
   glib_thread_cflags="$GLIB_CFLAGS"
-  glib_libs=`$GLIB_CONFIG glib gobject gmodule --libs`
+  glib_libs=`$GLIB_CONFIG glib gmodule --libs`
   glib_thread_libs="$GLIB_LIBS"
   GLIB_LIBS="$glib_libs"
   GLIB_DEPLIBS="$glib_libs"
@@ -276,10 +276,10 @@ else
   fi
 
   # For use in gtk-config
-  glib_cflags=`$GLIB_CONFIG --cflags gobject gmodule`
-  glib_thread_cflags=`$GLIB_CONFIG --cflags gobject gmodule gthread`
-  glib_libs=`$GLIB_CONFIG --libs gobject gmodule`
-  glib_thread_libs=`$GLIB_CONFIG --libs gobject gmodule gthread`
+  glib_cflags=`$GLIB_CONFIG --cflags gmodule`
+  glib_thread_cflags=`$GLIB_CONFIG --cflags gmodule gthread`
+  glib_libs=`$GLIB_CONFIG --libs gmodule`
+  glib_thread_libs=`$GLIB_CONFIG --libs gmodule gthread`
 
   glib_release=`$GLIB_CONFIG --version | sed 's%\\.[[0-9]]*$%%'`
 
@@ -294,7 +294,7 @@ else
   esac
 
   GLIB_CFLAGS="-I$glib_dir -I$glib_dir/gmodule"
-  GLIB_LIBS="$glib_dir/libglib.la $glib_dir/gmodule/libgobject.la $glib_dir/gmodule/libgmodule.la"
+  GLIB_LIBS="$glib_dir/libglib.la $glib_dir/gmodule/libgmodule.la"
   GLIB_DEPLIBS=
 
   AC_SUBST(GLIB_CFLAGS)
index 436af8d204b46eb15b2dc9ccea2a5fb0b2e45fa0..f86091d92eca7896b29809deaee581c2cb0b4217 100644 (file)
@@ -21,3 +21,6 @@ Incompatible Changes from GTK+-1.2 to GTK+-1.4:
   window's owner.
 
 - The detail arguments in the GtkStyleClass structure are now 'const gchar *'.
+
+- GtkColorSelectionDialog has now been moved into it's own set of files,
+gtkcolorseldialog.c and gtkcolorseldialog.h. 
index 296dda3e7f110bd455159608cc9d6943a832b7b9..6c2a2d6adf9ff1ddb83d0c3063f37ace1e8c70d8 100644 (file)
@@ -62,6 +62,7 @@ gtk_public_h_sources = @STRIP_BEGIN@ \
        gtkcheckmenuitem.h      \
        gtkclist.h              \
        gtkcolorsel.h           \
+       gtkcolorseldialog.h     \
        gtkcombo.h              \
        gtkcompat.h             \
        gtkcontainer.h          \
@@ -177,6 +178,7 @@ gtk_c_sources = @STRIP_BEGIN@ \
        gtkcheckmenuitem.c      \
        gtkclist.c              \
        gtkcolorsel.c           \
+       gtkcolorseldialog.c     \
        gtkcombo.c              \
        gtkcontainer.c          \
        gtkctree.c              \
@@ -202,6 +204,7 @@ gtk_c_sources = @STRIP_BEGIN@ \
        gtkhscale.c             \
        gtkhscrollbar.c         \
        gtkhseparator.c         \
+       gtkhsv.c                \
        gtkimage.c              \
        gtkinputdialog.c        \
        gtkintl.h               \
index e9cecef88abda87e2a383788249074b44433a493..6c1079fde796a1566cfd6aedbbab91d8604b7ba0 100644 (file)
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -46,6 +46,7 @@
 #include <gtk/gtkcheckmenuitem.h>
 #include <gtk/gtkclist.h>
 #include <gtk/gtkcolorsel.h>
+#include <gtk/gtkcolorseldialog.h>
 #include <gtk/gtkcombo.h>
 #include <gtk/gtkcompat.h>
 #include <gtk/gtkcontainer.h>
index 5e82acc6d9c560871dc7548e804b66812e50298e..6af300bd9eb154c03bae51699b3fa3e82bdca54a 100644 (file)
@@ -1,4 +1,5 @@
-/* GTK - The GIMP Toolkit
+ /* GTK - The GIMP Toolkit
+ * Copyright (C) 2000 Red Hat, Inc.
  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
  *
  * This library is free software; you can redistribute it and/or
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include <gdk/gdk.h>
+#include <glib.h>
+#include "gdk/gdkx.h"
+#include "gdk/gdkkeysyms.h"
 #include "gtkcolorsel.h"
+#include "gtkhsv.h"
 #include "gtkwindow.h"
+#include "gtkselection.h"
+#include "gtkdnd.h"
+#include "gtkdrawingarea.h"
+#include "gtksignal.h"
+#include "gtkhbox.h"
 #include "gtkhbbox.h"
+#include "gtkrc.h"
+#include "gtkframe.h"
+#include "gtktable.h"
+#include "gtklabel.h"
+#include "gtkpixmap.h"
+#include "gtkspinbutton.h"
+#include "gtkrange.h"
+#include "gtkhscale.h"
+#include "gtkentry.h"
+#include "gtkbutton.h"
+#include "gtkhseparator.h"
 #include "gtkintl.h"
-#include "gtkdnd.h"
-#include "gtkselection.h"
-
-/*
- * If you change the way the color values are stored,
- * please make sure to update the drag & drop support so it sends
- * across all the color info (currently RGBA). - Elliot
- */
-
-#ifndef M_PI
-#define M_PI    3.14159265358979323846
-#endif /* M_PI */
-
-#define DEGTORAD(a) (2.0*M_PI*a/360.0)
-#define SQR(a) (a*a)
-
-#define TIMER_DELAY 300
-
-#define CIRCLE_RADIUS 65
-
-#define WHEEL_WIDTH   2*CIRCLE_RADIUS+2
-#define WHEEL_HEIGHT  2*CIRCLE_RADIUS+2
-
-#define VALUE_WIDTH   32
-#define VALUE_HEIGHT  WHEEL_HEIGHT
-
-#define SAMPLE_WIDTH  WHEEL_WIDTH+VALUE_WIDTH+5
-#define SAMPLE_HEIGHT 28
-
-static void gtk_color_selection_class_init (GtkColorSelectionClass *klass);
-static void gtk_color_selection_set_arg    (GtkObject              *object,
-                                           GtkArg                 *arg,
-                                           guint                   arg_id);
-static void gtk_color_selection_get_arg    (GtkObject              *object,
-                                           GtkArg                 *arg,
-                                           guint                   arg_id);
-static void gtk_color_selection_init (GtkColorSelection *colorsel);
-static void gtk_color_selection_dialog_class_init (GtkColorSelectionDialogClass *klass);
-static void gtk_color_selection_dialog_init (GtkColorSelectionDialog *colorseldiag);
 
 enum {
   COLOR_CHANGED,
   LAST_SIGNAL
 };
 
-enum {
-  RGB_INPUTS     = 1 << 0,
-  HSV_INPUTS     = 1 << 1,
-  OPACITY_INPUTS = 1 << 2
-};
 
-enum {
-  SCALE,
-  ENTRY,
-  BOTH
-};
 
 enum {
-  HUE,
-  SATURATION,
-  VALUE,
-  RED,
-  GREEN,
-  BLUE,
-  OPACITY,
-  NUM_CHANNELS
+  COLORSEL_RED = 0,
+  COLORSEL_GREEN = 1,
+  COLORSEL_BLUE = 2,
+  COLORSEL_OPACITY = 3,
+  COLORSEL_HUE,
+  COLORSEL_SATURATION,
+  COLORSEL_VALUE,
+  COLORSEL_NUM_CHANNELS
 };
 
-enum {
-  ARG_0,
-  ARG_UPDATE_POLICY,
-  ARG_USE_OPACITY
-};
+typedef struct _ColorSelectionPrivate ColorSelectionPrivate;
 
-typedef struct
-{
-  gchar *label;
-  gfloat lower, upper, step_inc, page_inc;
-  GtkSignalFunc updater;
-} scale_val_type;
-
-
-#define HSV_TO_RGB()  gtk_color_selection_hsv_to_rgb( \
-                        colorsel->values[HUE], \
-                        colorsel->values[SATURATION], \
-                        colorsel->values[VALUE], \
-                        &colorsel->values[RED], \
-                        &colorsel->values[GREEN], \
-                        &colorsel->values[BLUE])
-
-#define RGB_TO_HSV()  gtk_color_selection_rgb_to_hsv( \
-                        colorsel->values[RED], \
-                        colorsel->values[GREEN], \
-                        colorsel->values[BLUE], \
-                        &colorsel->values[HUE], \
-                        &colorsel->values[SATURATION], \
-                        &colorsel->values[VALUE])
-
-
-static void gtk_color_selection_hsv_updater       (GtkWidget         *widget,
-                                                   gpointer           data);
-static void gtk_color_selection_rgb_updater       (GtkWidget         *widget,
-                                                   gpointer           data);
-static void gtk_color_selection_opacity_updater   (GtkWidget         *widget,
-                                                   gpointer           data);
-static void gtk_color_selection_realize           (GtkWidget         *widget);
-static void gtk_color_selection_unrealize         (GtkWidget         *widget);
-static void gtk_color_selection_finalize          (GtkObject         *object);
-static void gtk_color_selection_color_changed     (GtkColorSelection *colorsel);
-static void gtk_color_selection_update_input      (GtkWidget         *scale,
-                                                   GtkWidget         *entry,
-                                                   gdouble            value);
-static void gtk_color_selection_update_inputs     (GtkColorSelection *colorsel,
-                                                   gint               inputs,
-                                                   gint               which);
-static void gtk_color_selection_update_value      (GtkColorSelection *colorsel,
-                                                   gint               y);
-static void gtk_color_selection_update_wheel      (GtkColorSelection *colorsel,
-                                                   gint               x,
-                                                   gint               y);
-static void gtk_color_selection_value_resize      (GtkWidget          *widget,
-                                                   gpointer            data);
-static gint gtk_color_selection_value_events      (GtkWidget          *area,
-                                                   GdkEvent           *event);
-static gint gtk_color_selection_value_timeout     (GtkColorSelection  *colorsel);
-static void gtk_color_selection_wheel_resize      (GtkWidget          *widget,
-                                                   gpointer            data);
-static gint gtk_color_selection_wheel_events      (GtkWidget          *area,
-                                                   GdkEvent           *event);
-static gint gtk_color_selection_wheel_timeout     (GtkColorSelection  *colorsel);
-static void gtk_color_selection_sample_resize     (GtkWidget          *widget,
-                                                   gpointer            data);
-static void gtk_color_selection_drag_begin        (GtkWidget          *widget,
-                                                  GdkDragContext     *context,
-                                                  gpointer            data);
-static void gtk_color_selection_drag_end          (GtkWidget          *widget,
-                                                  GdkDragContext     *context,
-                                                  gpointer            data);
-static void gtk_color_selection_drop_handle       (GtkWidget          *widget, 
-                                                  GdkDragContext     *context,
-                                                  gint                x,
-                                                  gint                y,
-                                                  GtkSelectionData   *selection_data,
-                                                  guint               info,
-                                                  guint               time,
-                                                  gpointer            data);
-static void gtk_color_selection_drag_handle       (GtkWidget        *widget, 
-                                                  GdkDragContext   *context,
-                                                  GtkSelectionData *selection_data,
-                                                  guint             info,
-                                                  guint             time,
-                                                  gpointer          data);
-static void gtk_color_selection_draw_wheel_marker (GtkColorSelection  *colorsel);
-static void gtk_color_selection_draw_wheel_frame  (GtkColorSelection  *colorsel);
-static void gtk_color_selection_draw_value_marker (GtkColorSelection  *colorsel);
-static void gtk_color_selection_draw_value_bar    (GtkColorSelection  *colorsel,
-                                                   gint                resize);
-static void gtk_color_selection_draw_wheel        (GtkColorSelection  *colorsel,
-                                                   gint                resize);
-static void gtk_color_selection_draw_sample       (GtkColorSelection  *colorsel,
-                                                   gint                resize);
-
-static gint gtk_color_selection_eval_wheel        (gint     x, gint     y,
-                                                  gdouble cx, gdouble cy,
-                                                  gdouble *h, gdouble *s);
-
-static void gtk_color_selection_hsv_to_rgb        (gdouble  h, gdouble  s, gdouble  v,
-                                                  gdouble *r, gdouble *g, gdouble *b);
-static void gtk_color_selection_rgb_to_hsv        (gdouble  r, gdouble  g, gdouble  b,
-                                                  gdouble *h, gdouble *s, gdouble *v);
-
-
-static GtkVBoxClass *color_selection_parent_class = NULL;
-static GtkWindowClass *color_selection_dialog_parent_class = NULL;
-
-
-static guint color_selection_signals[LAST_SIGNAL] = {0};
-
-static const gchar     *value_index_key = "gtk-value-index";
-
-
-#define SF GtkSignalFunc
-
-
-static const scale_val_type scale_vals[NUM_CHANNELS] =
+struct _ColorSelectionPrivate
 {
-  {N_("Hue:"),        0.0, 360.0, 1.00, 10.00, (SF) gtk_color_selection_hsv_updater},
-  {N_("Saturation:"), 0.0,   1.0, 0.01,  0.01, (SF) gtk_color_selection_hsv_updater},
-  {N_("Value:"),      0.0,   1.0, 0.01,  0.01, (SF) gtk_color_selection_hsv_updater},
-  {N_("Red:"),        0.0,   1.0, 0.01,  0.01, (SF) gtk_color_selection_rgb_updater},
-  {N_("Green:"),      0.0,   1.0, 0.01,  0.01, (SF) gtk_color_selection_rgb_updater},
-  {N_("Blue:"),       0.0,   1.0, 0.01,  0.01, (SF) gtk_color_selection_rgb_updater},
-  {N_("Opacity:"),    0.0,   1.0, 0.01,  0.01, (SF) gtk_color_selection_opacity_updater}
+  /* < Private > */
+  gboolean use_opacity;
+  gboolean use_palette;
+  gboolean changing;
+  gboolean default_set;
+
+  gdouble color[COLORSEL_NUM_CHANNELS];
+  gdouble old_color[COLORSEL_NUM_CHANNELS];
+
+  GtkWidget *triangle_colorsel;
+  GtkWidget *hue_spinbutton;
+  GtkWidget *sat_spinbutton;
+  GtkWidget *val_spinbutton;
+  GtkWidget *red_spinbutton;
+  GtkWidget *green_spinbutton;
+  GtkWidget *blue_spinbutton;
+  GtkWidget *opacity_slider;
+  GtkWidget *opacity_label;
+  GtkWidget *opacity_entry;
+  GtkWidget *palette_frame;
+  GtkWidget *hex_entry;
+
+  /* The Palette code */
+  GtkWidget *custom_palette [CUSTOM_PALETTE_WIDTH][CUSTOM_PALETTE_HEIGHT];
+  GtkWidget *last_palette;
+
+  /* The color_sample stuff */
+  GtkWidget *sample_area;
+  GtkWidget *old_sample;
+  GtkWidget *cur_sample;
+  GtkWidget *colorsel;
+
+  /* The color dropper */
+  gboolean moving_dropper;
 };
 
-GtkType
-gtk_color_selection_get_type (void)
-{
-  static GtkType color_selection_type = 0;
 
-  if (!color_selection_type)
-    {
-      static const GtkTypeInfo colorsel_info =
-      {
-       "GtkColorSelection",
-       sizeof (GtkColorSelection),
-       sizeof (GtkColorSelectionClass),
-       (GtkClassInitFunc) gtk_color_selection_class_init,
-       (GtkObjectInitFunc) gtk_color_selection_init,
-       /* reserved_1 */ NULL,
-       /* reserved_2 */ NULL,
-        (GtkClassInitFunc) NULL,
-      };
+static void gtk_color_selection_init           (GtkColorSelection               *colorsel);
+static void gtk_color_selection_class_init     (GtkColorSelectionClass  *klass);
+static void gtk_color_selection_destroy        (GtkObject *object);
+static void update_color (GtkColorSelection *colorsel);
+
+static GtkVBoxClass *parent_class = NULL;
+static guint color_selection_signals[LAST_SIGNAL] = { 0 };
+
+
+/* The cursor for the dropper */
+#define DROPPER_WIDTH 17
+#define DROPPER_HEIGHT 17
+#define DROPPER_X_HOT 2
+#define DROPPER_Y_HOT 16
+
+
+static char dropper_bits[] = {
+  0xff, 0x8f, 0x01, 0xff, 0x77, 0x01, 0xff, 0xfb, 0x00, 0xff, 0xf8, 0x00,
+  0x7f, 0xff, 0x00, 0xff, 0x7e, 0x01, 0xff, 0x9d, 0x01, 0xff, 0xd8, 0x01,
+  0x7f, 0xd4, 0x01, 0x3f, 0xee, 0x01, 0x1f, 0xff, 0x01, 0x8f, 0xff, 0x01,
+  0xc7, 0xff, 0x01, 0xe3, 0xff, 0x01, 0xf3, 0xff, 0x01, 0xfd, 0xff, 0x01,
+  0xff, 0xff, 0x01, };
+
+static char dropper_mask[] = {
+  0x00, 0x70, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xff, 0x01,
+  0x80, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x80, 0x3f, 0x00,
+  0xc0, 0x3f, 0x00, 0xe0, 0x13, 0x00, 0xf0, 0x01, 0x00, 0xf8, 0x00, 0x00,
+  0x7c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x0d, 0x00, 0x00,
+  0x02, 0x00, 0x00, };
+
+static GdkCursor *picker_cursor = NULL;
+
+
+/* XPM */
+static char *picker[] = {
+  /* columns rows colors chars-per-pixel */
+  "25 25 8 1",
+  "  c Gray0",
+  ". c #020202",
+  "X c Gray12",
+  "o c Gray13",
+  "O c Gray52",
+  "+ c #929292",
+  "@ c Gray100",
+  "# c None",
+  /* pixels */
+  "#########################",
+  "#########################",
+  "#########################",
+  "#########################",
+  "#########################",
+  "#################   #####",
+  "################     ####",
+  "################     +###",
+  "#############        +###",
+  "##############      ++###",
+  "#############+@   +++####",
+  "############+@@@  +######",
+  "###########+@@@ + +######",
+  "##########+@@@ ++#+######",
+  "#########+@@@ ++#########",
+  "########+@@@ ++##########",
+  "#######+@@@ ++###########",
+  "######+@@@ ++############",
+  "######+@@ ++#############",
+  "#####+@  ++##############",
+  "###### +++###############",
+  "#########################",
+  "#########################",
+  "#########################",
+  "#########################"
+};
 
-      color_selection_type = gtk_type_unique (GTK_TYPE_VBOX, &colorsel_info);
-    }
 
-  return color_selection_type;
-}
+/*
+ *
+ * The Sample Color
+ *
+ */
+#define SAMPLE_WIDTH  64
+#define SAMPLE_HEIGHT 28
+
+static void color_sample_draw_sample (GtkColorSelection *colorsel, int which);
+static void color_sample_draw_samples (GtkColorSelection *colorsel);
 
 static void
-gtk_color_selection_class_init (GtkColorSelectionClass *klass)
+color_sample_drag_begin (GtkWidget      *widget,
+                        GdkDragContext *context,
+                        gpointer        data)
 {
-  GtkObjectClass *object_class;
-  GtkWidgetClass *widget_class;
-  GtkContainerClass *container_class;
+  GtkColorSelection *colorsel = data;
+  ColorSelectionPrivate *priv;
+  GtkWidget *window;
+  gdouble colors[4];
+  gdouble *colsrc;
+  GdkColor bg;
+  gint n, i;
 
-  object_class = (GtkObjectClass*) klass;
-  widget_class = (GtkWidgetClass*) klass;
-  container_class = (GtkContainerClass*) klass;
+  priv = colorsel->private;
+  window = gtk_window_new (GTK_WINDOW_POPUP);
+  gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
+  gtk_widget_set_usize (window, 48, 32);
+  gtk_widget_realize (window);
+  gtk_object_set_data_full (GTK_OBJECT (widget),
+                           "gtk-color-selection-drag-window",
+                           window,
+                           (GtkDestroyNotify) gtk_widget_destroy);
 
-  color_selection_parent_class = gtk_type_class (GTK_TYPE_VBOX);
-  
-  gtk_object_add_arg_type ("GtkColorSelection::policy", GTK_TYPE_UPDATE_TYPE,
-                          GTK_ARG_READWRITE, ARG_UPDATE_POLICY);
-  gtk_object_add_arg_type ("GtkColorSelection::use_opacity", GTK_TYPE_BOOL,
-                          GTK_ARG_READWRITE, ARG_USE_OPACITY);
-  
-  color_selection_signals[COLOR_CHANGED] =
-     gtk_signal_new ("color_changed",
-                    GTK_RUN_FIRST,
-                     object_class->type,
-                    GTK_SIGNAL_OFFSET (GtkColorSelectionClass, color_changed),
-                     gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0);
+  if (widget == priv->old_sample)
+    colsrc = priv->old_color;
+  else
+    colsrc = priv->color;
 
-  gtk_object_class_add_signals (object_class, color_selection_signals, LAST_SIGNAL);
+  for (i=0, n = COLORSEL_RED; n <= COLORSEL_BLUE; n++)
+    {
+      colors[i++] = colsrc[n];
+    }
+
+  if (priv->use_opacity)
+    {
+      colors[i] = colsrc[COLORSEL_OPACITY];
+    }
 
-  object_class->set_arg = gtk_color_selection_set_arg;
-  object_class->get_arg = gtk_color_selection_get_arg;
-  object_class->finalize = gtk_color_selection_finalize;
+  bg.red = 0xffff * colors[0];
+  bg.green = 0xffff * colors[1];
+  bg.blue = 0xffff * colors[2];
 
-  widget_class->realize = gtk_color_selection_realize;
-  widget_class->unrealize = gtk_color_selection_unrealize;
+  gdk_color_alloc (gtk_widget_get_colormap (window), &bg);
+  gdk_window_set_background (window->window, &bg);
+
+  gtk_drag_set_icon_widget (context, window, -2, -2);
 }
 
 static void
-gtk_color_selection_init (GtkColorSelection *colorsel)
+color_sample_drag_end (GtkWidget      *widget,
+                      GdkDragContext *context,
+                      gpointer        data)
 {
-  GtkWidget *frame, *hbox, *vbox, *hbox2, *label, *table;
-  GtkObject *adj;
-  gint old_mask, n;
-  gchar txt[32];
-
-  for (n = RED; n <= OPACITY; n++)
-    colorsel->values[n] = 1.0;
-
-  RGB_TO_HSV ();
-
-  for (n = HUE; n <= OPACITY; n++)
-    colorsel->old_values[n] = colorsel->values[n];
-
-  colorsel->wheel_gc = NULL;
-  colorsel->value_gc = NULL;
-  colorsel->sample_gc = NULL;
-  colorsel->wheel_buf = NULL;
-  colorsel->value_buf = NULL;
-  colorsel->sample_buf = NULL;
-
-  colorsel->use_opacity = FALSE;
-  colorsel->timer_active = FALSE;
-  colorsel->policy = GTK_UPDATE_CONTINUOUS;
-
-  hbox = gtk_hbox_new (FALSE, 5);
-  gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
-  gtk_container_add (GTK_CONTAINER (colorsel), hbox);
-
-  vbox = gtk_vbox_new (FALSE, 5);
-  gtk_container_add (GTK_CONTAINER (hbox), vbox);
-  gtk_widget_show (vbox);
-
-  hbox2 = gtk_hbox_new (FALSE, 5);
-  gtk_container_add (GTK_CONTAINER (vbox), hbox2);
-  gtk_widget_show (hbox2);
-
-  colorsel->wheel_area = gtk_preview_new (GTK_PREVIEW_COLOR);
-  old_mask = gtk_widget_get_events(colorsel->wheel_area);
-  gtk_widget_set_events (colorsel->wheel_area,
-                        old_mask |
-                        GDK_BUTTON_PRESS_MASK |
-                        GDK_BUTTON_RELEASE_MASK |
-                        GDK_BUTTON_MOTION_MASK |
-                        GDK_POINTER_MOTION_HINT_MASK);
-  gtk_preview_size (GTK_PREVIEW (colorsel->wheel_area), WHEEL_WIDTH, WHEEL_HEIGHT);
-  gtk_preview_set_expand (GTK_PREVIEW (colorsel->wheel_area), TRUE);
-  gtk_container_add (GTK_CONTAINER (hbox2), colorsel->wheel_area);
-  gtk_widget_show (colorsel->wheel_area);
-
-  old_mask = gtk_widget_get_events (colorsel->wheel_area);
-
-  gtk_signal_connect (GTK_OBJECT (colorsel->wheel_area), "event",
-    (SF) gtk_color_selection_wheel_events, (gpointer) colorsel->wheel_area);
-  gtk_signal_connect_after (GTK_OBJECT (colorsel->wheel_area), "expose_event",
-    (SF) gtk_color_selection_wheel_events, (gpointer) colorsel->wheel_area);
-  gtk_signal_connect_after (GTK_OBJECT (colorsel->wheel_area), "size_allocate",
-    (SF) gtk_color_selection_wheel_resize, (gpointer) colorsel->wheel_area);
-  gtk_object_set_data (GTK_OBJECT (colorsel->wheel_area), "_GtkColorSelection", (gpointer) colorsel);
+  gtk_object_set_data (GTK_OBJECT (widget), "gtk-color-selection-drag-window", NULL);
+}
 
-  frame = gtk_frame_new (NULL);
-  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
-  gtk_container_set_border_width (GTK_CONTAINER (frame), 0);
-  gtk_box_pack_start (GTK_BOX (hbox2), frame, FALSE, TRUE, 0);
-  gtk_widget_show (frame);
-
-  colorsel->value_area = gtk_preview_new (GTK_PREVIEW_COLOR);
-  gtk_preview_size (GTK_PREVIEW (colorsel->value_area), VALUE_WIDTH, VALUE_HEIGHT);
-  gtk_preview_set_expand (GTK_PREVIEW (colorsel->value_area), TRUE);
-  gtk_container_add (GTK_CONTAINER (frame), colorsel->value_area);
-  gtk_widget_show (colorsel->value_area);
-
-  old_mask = gtk_widget_get_events (colorsel->value_area);
-  gtk_widget_set_events (colorsel->value_area,
-                        old_mask |
-                        GDK_BUTTON_PRESS_MASK |
-                        GDK_BUTTON_RELEASE_MASK |
-                        GDK_BUTTON_MOTION_MASK |
-                        GDK_POINTER_MOTION_HINT_MASK);
-
-  gtk_signal_connect_after (GTK_OBJECT (colorsel->value_area), "expose_event",
-    (SF) gtk_color_selection_value_events, (gpointer) colorsel->value_area);
-  gtk_signal_connect_after (GTK_OBJECT (colorsel->value_area), "size_allocate",
-    (SF) gtk_color_selection_value_resize, (gpointer) colorsel->value_area);
-  gtk_signal_connect (GTK_OBJECT (colorsel->value_area), "event",
-    (SF) gtk_color_selection_value_events, (gpointer) colorsel->value_area);
-  gtk_object_set_data (GTK_OBJECT (colorsel->value_area), "_GtkColorSelection", (gpointer) colorsel);
-
-  /* New/old color samples */
-  /* ===================== */
+static void
+color_sample_drop_handle (GtkWidget        *widget,
+                         GdkDragContext   *context,
+                         gint              x,
+                         gint              y,
+                         GtkSelectionData *selection_data,
+                         guint             info,
+                         guint             time,
+                         gpointer          data)
+{
+  GtkColorSelection *colorsel = data;
+  ColorSelectionPrivate *priv;
+  guint16 *vals;
+  gdouble color[4];
+  priv = colorsel->private;
 
-  frame = gtk_frame_new (NULL);
-  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
-  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
-  gtk_widget_show (frame);
-
-/*  colorsel->sample_area_eb = gtk_button_new ();
-  gtk_container_add (GTK_CONTAINER (frame), colorsel->sample_area_eb);
-  gtk_widget_show (colorsel->sample_area_eb); */
-
-  colorsel->sample_area = gtk_preview_new (GTK_PREVIEW_COLOR);
-  gtk_preview_size (GTK_PREVIEW (colorsel->sample_area), SAMPLE_WIDTH, SAMPLE_HEIGHT);
-  gtk_preview_set_expand (GTK_PREVIEW (colorsel->sample_area), TRUE);
-  gtk_container_add (GTK_CONTAINER (frame),
-                    colorsel->sample_area);
-  gtk_widget_set_events(colorsel->sample_area,
-               gtk_widget_get_events(colorsel->sample_area)
-               | GDK_BUTTON_MOTION_MASK
-               | GDK_BUTTON_PRESS_MASK
-               | GDK_BUTTON_RELEASE_MASK
-               | GDK_ENTER_NOTIFY_MASK
-               | GDK_LEAVE_NOTIFY_MASK);
-  gtk_widget_show (colorsel->sample_area);
-
-  gtk_signal_connect_after (GTK_OBJECT (colorsel->sample_area),
-                           "size_allocate",
-                           GTK_SIGNAL_FUNC (gtk_color_selection_sample_resize),
-                           colorsel->sample_area);
-  gtk_object_set_data (GTK_OBJECT (colorsel->sample_area), "_GtkColorSelection", (gpointer) colorsel);
-
-  table = gtk_table_new (NUM_CHANNELS, 3, FALSE);
-  gtk_table_set_col_spacings (GTK_TABLE (table), 3);
-  gtk_box_pack_start (GTK_BOX (hbox), table, FALSE, TRUE, 0);
-
-  for (n = HUE; n <= OPACITY; n++)
-    {
-      label = gtk_label_new (_(scale_vals[n].label));
-      gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
-      gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, n, n + 1);
-
-      adj = gtk_adjustment_new (colorsel->values[n], scale_vals[n].lower,
-                               scale_vals[n].upper, scale_vals[n].step_inc,
-                                scale_vals[n].page_inc, 0.0);
-      colorsel->scales[n] = gtk_hscale_new (GTK_ADJUSTMENT (adj));
-      gtk_widget_set_usize (colorsel->scales[n], 128, 0);
-      gtk_scale_set_value_pos (GTK_SCALE (colorsel->scales[n]), GTK_POS_TOP);
-
-      gtk_range_set_update_policy (GTK_RANGE (colorsel->scales[n]), colorsel->policy);
-      gtk_scale_set_draw_value (GTK_SCALE (colorsel->scales[n]), FALSE);
-      gtk_scale_set_digits (GTK_SCALE (colorsel->scales[n]), 2);
-      gtk_table_attach_defaults (GTK_TABLE (table), colorsel->scales[n], 1, 2, n, n + 1);
-
-      colorsel->entries[n] = gtk_entry_new ();
-      gtk_widget_set_usize (colorsel->entries[n], 40, 0);
-      sprintf (txt, "%.2f", colorsel->values[n]);
-      gtk_entry_set_text (GTK_ENTRY (colorsel->entries[n]), txt);
-      gtk_table_attach_defaults (GTK_TABLE (table), colorsel->entries[n], 2, 3, n, n + 1);
-
-      if (n != OPACITY)
-       {
-         gtk_widget_show (label);
-         gtk_widget_show (colorsel->scales[n]);
-         gtk_widget_show (colorsel->entries[n]);
-       }
+  /* This is currently a guint16 array of the format:
+   * R
+   * G
+   * B
+   * opacity
+   */
 
-      gtk_signal_connect_object (GTK_OBJECT (adj), "value_changed",
-                                 scale_vals[n].updater, (gpointer) colorsel->scales[n]);
-      gtk_object_set_data (GTK_OBJECT (colorsel->scales[n]), "_GtkColorSelection", (gpointer) colorsel);
-      gtk_object_set_data (GTK_OBJECT (colorsel->scales[n]), value_index_key, GINT_TO_POINTER (n));
-      gtk_signal_connect_object (GTK_OBJECT (colorsel->entries[n]), "changed",
-                                 scale_vals[n].updater, (gpointer) colorsel->entries[n]);
-      gtk_object_set_data (GTK_OBJECT (colorsel->entries[n]), "_GtkColorSelection", (gpointer) colorsel);
-      gtk_object_set_data (GTK_OBJECT (colorsel->entries[n]), value_index_key, GINT_TO_POINTER (n));
+  if (selection_data->length < 0)
+    return;
+
+  if ((selection_data->format != 16) ||
+      (selection_data->length != 8))
+    {
+      g_warning ("Received invalid color data\n");
+      return;
     }
 
-  colorsel->opacity_label = label;
-  
-  gtk_widget_show (table);
-  gtk_widget_show (hbox);
-}
+  vals = (guint16 *)selection_data->data;
 
-static void
-gtk_color_selection_set_arg (GtkObject *object,
-                            GtkArg    *arg,
-                            guint      arg_id)
-{
-  GtkColorSelection *color_selection = GTK_COLOR_SELECTION (object);
-  
-  switch (arg_id)
+  if (widget == priv->cur_sample)
     {
-    case ARG_UPDATE_POLICY:
-      gtk_color_selection_set_update_policy (color_selection, GTK_VALUE_ENUM (*arg));
-      break;
-    case ARG_USE_OPACITY:
-      gtk_color_selection_set_opacity (color_selection, GTK_VALUE_BOOL (*arg));
-      break;  
+      color[0] = (gdouble)vals[0] / 0xffff;
+      color[1] = (gdouble)vals[1] / 0xffff;
+      color[2] = (gdouble)vals[2] / 0xffff;
+      color[3] = (gdouble)vals[3] / 0xffff;
+
+      gtk_color_selection_set_color (colorsel, color);
     }
 }
 
 static void
-gtk_color_selection_get_arg (GtkObject *object,
-                            GtkArg    *arg,
-                            guint      arg_id)
+color_sample_drag_handle (GtkWidget        *widget,
+                         GdkDragContext   *context,
+                         GtkSelectionData *selection_data,
+                         guint             info,
+                         guint             time,
+                         gpointer          data)
 {
-  GtkColorSelection *color_selection;
-  
-  color_selection = GTK_COLOR_SELECTION (object);
-  
-  switch (arg_id)
-    {
-    case ARG_UPDATE_POLICY:
-      GTK_VALUE_ENUM (*arg) = color_selection->policy;
-      break;
-    case ARG_USE_OPACITY:
-      GTK_VALUE_BOOL (*arg) = color_selection->use_opacity;
-      break;
-    default:
-      break;
-    }
-}
+  GtkColorSelection *colorsel = data;
+  ColorSelectionPrivate *priv;
+  guint16 vals[4];
+  gdouble *colsrc;
 
-GtkWidget*
-gtk_color_selection_new (void)
-{
-  GtkColorSelection *colorsel;
+  priv = colorsel->private;
 
-  colorsel = gtk_type_new (GTK_TYPE_COLOR_SELECTION);
+  if (widget == priv->old_sample)
+    colsrc = priv->old_color;
+  else
+    colsrc = priv->color;
 
-  return GTK_WIDGET (colorsel);
+  vals[0] = colsrc[COLORSEL_RED] * 0xffff;
+  vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
+  vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
+  vals[3] = priv->use_opacity ? colsrc[COLORSEL_OPACITY] * 0xffff : 0xffff;
+
+  gtk_selection_data_set (selection_data,
+                         gdk_atom_intern ("application/x-color", FALSE),
+                         16, (guchar *)vals, 8);
 }
 
-void
-gtk_color_selection_set_update_policy (GtkColorSelection *colorsel,
-                                      GtkUpdateType      policy)
+/* which = 0 means draw old sample, which = 1 means draw new */
+static void
+color_sample_draw_sample (GtkColorSelection *colorsel, int which)
 {
-  gint n;
+  GtkWidget *da;
+  gint x, y, i, wid, heig, f, n, goff;
+  guchar c[3 * 2], cc[3 * 4], *cp = c;
+  gdouble o;
+  guchar *buf;
+  ColorSelectionPrivate *priv;
 
   g_return_if_fail (colorsel != NULL);
+  priv = colorsel->private;
 
-  if (policy != colorsel->policy)
-    {
-      colorsel->policy = policy;
+  g_return_if_fail (priv->sample_area != NULL);
+  if (!GTK_WIDGET_DRAWABLE (priv->sample_area))
+    return;
 
-      for (n = 0; n < NUM_CHANNELS; n++)
-       gtk_range_set_update_policy (GTK_RANGE (colorsel->scales[n]), policy);
+  if (which == 0)
+    {
+      da = priv->old_sample;
+      for (n = 0, i = COLORSEL_RED; n < 3; n++, i++)
+       c[n] = (guchar) (255.0 * priv->old_color[i]);
+      goff = 0;
+    }
+  else
+    {
+      da = priv->cur_sample;
+      for (n = 0, i = COLORSEL_RED; n < 3; n++, i++)
+       c[n] = (guchar) (255.0 * priv->color[i]);
+      goff =  priv->old_sample->allocation.width % 32;
     }
-}
 
+  wid = da->allocation.width;
+  heig = da->allocation.height;
 
-void
-gtk_color_selection_set_color (GtkColorSelection *colorsel,
-                              gdouble           *color)
-{
-  gint n, i = 0;
+  buf = g_new(guchar, 3 * wid * heig);
 
-  g_return_if_fail (colorsel != NULL);
-  g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
-
-  if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (colorsel)))
-    gtk_color_selection_draw_wheel_marker (colorsel);
+#if 0
+  i = COLORSEL_RED;
+  for (n = 0; n < 3; n++)
+    {
+      c[n] = (guchar) (255.0 * priv->old_color[i]);
+      c[n + 3] = (guchar) (255.0 * priv->color[i++]);
+    }
+#endif
 
-  for (n = RED; n <= BLUE; n++)
+  if (priv->use_opacity)
     {
-      colorsel->old_values[n] = colorsel->values[n];
-      colorsel->values[n] = color[i++];
+      o = (which) ? priv->color[COLORSEL_OPACITY] : priv->old_color[COLORSEL_OPACITY];
+
+      for (n = 0; n < 3; n++)
+       {
+         cc[n] = (guchar) ((1.0 - o) * 192 + (o * (gdouble) c[n]));
+         cc[n + 3] = (guchar) ((1.0 - o) * 128 + (o * (gdouble) c[n]));
+       }
+      cp = cc;
     }
 
-  if (colorsel->use_opacity)
+  i = 0;
+  for (y = 0; y < heig; y++)
     {
-      colorsel->old_values[OPACITY] = colorsel->values[OPACITY];
-      colorsel->values[OPACITY] = color[i];
+      for (x = 0; x < wid; x++)
+       {
+         if (priv->use_opacity)
+           f = 3 * ((((goff + x) % 32) < 16) ^ ((y % 32) < 16));
+         else
+           f = 0;
+
+         for (n = 0; n < 3; n++)
+           buf[i++] = cp[n + f];
+       }
     }
 
-  RGB_TO_HSV ();
+  gdk_draw_rgb_image(da->window,
+                    da->style->black_gc,
+                    0, 0,
+                    wid, heig,
+                    GDK_RGB_DITHER_NORMAL,
+                    buf,
+                    3*wid);
 
-  gtk_color_selection_update_inputs (colorsel, RGB_INPUTS | HSV_INPUTS | OPACITY_INPUTS, BOTH);
 
-  if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (colorsel)))
-    {
-      gtk_color_selection_draw_value_bar (colorsel, FALSE);
-      gtk_color_selection_draw_sample (colorsel, FALSE);
-      gtk_color_selection_draw_wheel_marker (colorsel);
-    }
+  g_free (buf);
+
 }
 
-void
-gtk_color_selection_get_color (GtkColorSelection *colorsel,
-                              gdouble           *color)
-{
-  gint n, i = 0;
 
-  g_return_if_fail (colorsel != NULL);
-  g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
+static void
+color_sample_draw_samples (GtkColorSelection *colorsel)
+{
+  color_sample_draw_sample (colorsel, 0);
+  color_sample_draw_sample (colorsel, 1);
+}
 
-  for (n = RED; n <= BLUE; n++)
-    color[i++] = colorsel->values[n];
-  if (colorsel->use_opacity)
-    color[i] = colorsel->values[OPACITY];
+static void
+color_old_sample_expose(GtkWidget* da, GdkEventExpose* event, GtkColorSelection *colorsel)
+{
+  color_sample_draw_sample (colorsel, 0);
 }
 
+
 static void
-gtk_color_selection_realize (GtkWidget         *widget)
+color_cur_sample_expose(GtkWidget* da, GdkEventExpose* event, GtkColorSelection *colorsel)
 {
-  GtkColorSelection *colorsel;
+  color_sample_draw_sample (colorsel, 1);
+}
 
+static void
+color_sample_setup_dnd (GtkColorSelection *colorsel, GtkWidget *sample)
+{
   static const GtkTargetEntry targets[] = {
     { "application/x-color", 0 }
   };
+  ColorSelectionPrivate *priv;
+  priv = colorsel->private;
 
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_COLOR_SELECTION (widget));
-
-  colorsel = GTK_COLOR_SELECTION (widget);
-
-  if (GTK_WIDGET_CLASS (color_selection_parent_class)->realize)
-    (*GTK_WIDGET_CLASS (color_selection_parent_class)->realize) (widget);
-
-  gtk_drag_dest_set (colorsel->sample_area,
-                      GTK_DEST_DEFAULT_HIGHLIGHT |
-                      GTK_DEST_DEFAULT_MOTION |
-                      GTK_DEST_DEFAULT_DROP,
-                      targets, 1,
-                      GDK_ACTION_COPY);
-
-  gtk_drag_source_set (colorsel->sample_area, 
+  gtk_drag_source_set (sample,
                       GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
                       targets, 1,
                       GDK_ACTION_COPY | GDK_ACTION_MOVE);
 
-  gtk_signal_connect (GTK_OBJECT (colorsel->sample_area),
+  gtk_signal_connect (GTK_OBJECT (sample),
                      "drag_begin",
-                     GTK_SIGNAL_FUNC (gtk_color_selection_drag_begin),
+                     GTK_SIGNAL_FUNC (color_sample_drag_begin),
                      colorsel);
-  gtk_signal_connect (GTK_OBJECT (colorsel->sample_area),
-                     "drag_end",
-                     GTK_SIGNAL_FUNC (gtk_color_selection_drag_end),
-                     colorsel);
-  gtk_signal_connect (GTK_OBJECT (colorsel->sample_area),
+  if (sample == priv->cur_sample)
+    {
+
+      gtk_drag_dest_set (sample,
+                        GTK_DEST_DEFAULT_HIGHLIGHT |
+                        GTK_DEST_DEFAULT_MOTION |
+                        GTK_DEST_DEFAULT_DROP,
+                        targets, 1,
+                        GDK_ACTION_COPY);
+
+      gtk_signal_connect (GTK_OBJECT (sample),
+                         "drag_end",
+                         GTK_SIGNAL_FUNC (color_sample_drag_end),
+                         colorsel);
+    }
+
+  gtk_signal_connect (GTK_OBJECT (sample),
                      "drag_data_get",
-                     GTK_SIGNAL_FUNC (gtk_color_selection_drag_handle),
+                     GTK_SIGNAL_FUNC (color_sample_drag_handle),
                      colorsel);
-  gtk_signal_connect (GTK_OBJECT (colorsel->sample_area),
+  gtk_signal_connect (GTK_OBJECT (sample),
                      "drag_data_received",
-                     GTK_SIGNAL_FUNC (gtk_color_selection_drop_handle),
+                     GTK_SIGNAL_FUNC (color_sample_drop_handle),
                      colorsel);
+
 }
 
+
 static void
-gtk_color_selection_unrealize (GtkWidget      *widget)
+color_sample_new (GtkColorSelection *colorsel)
 {
-  GtkColorSelection *colorsel;
+  ColorSelectionPrivate *priv;
 
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_COLOR_SELECTION (widget));
+  priv = colorsel->private;
 
-  colorsel = GTK_COLOR_SELECTION (widget);
+  gtk_widget_push_visual(gdk_rgb_get_visual());
+  gtk_widget_push_colormap(gdk_rgb_get_cmap());
 
-  if (colorsel->value_gc != NULL)
-    {
-      gdk_gc_unref (colorsel->value_gc);
-      colorsel->value_gc = NULL;
-    }
-  if (colorsel->wheel_gc != NULL)
-    {
-      gdk_gc_unref (colorsel->wheel_gc);
-      colorsel->wheel_gc = NULL;
-    }
-  if (colorsel->sample_gc != NULL)
-    {
-      gdk_gc_unref (colorsel->sample_gc);
-      colorsel->sample_gc = NULL;
-    }
-
-  (* GTK_WIDGET_CLASS (color_selection_parent_class)->unrealize) (widget);
-}
-
-static void
-gtk_color_selection_finalize (GtkObject *object)
-{
-  GtkColorSelection *colorsel;
+  priv->sample_area = gtk_hbox_new (FALSE, 0);
+  priv->old_sample = gtk_drawing_area_new ();
+  priv->cur_sample = gtk_drawing_area_new ();
 
-  g_return_if_fail (object != NULL);
-  g_return_if_fail (GTK_IS_COLOR_SELECTION (object));
+  gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->old_sample,
+                     TRUE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->cur_sample,
+                     TRUE, TRUE, 0);
+  gtk_widget_pop_visual();
+  gtk_widget_pop_colormap();
 
-  colorsel = GTK_COLOR_SELECTION (object);
+  gtk_signal_connect(GTK_OBJECT (priv->old_sample), "expose_event",
+                    GTK_SIGNAL_FUNC (color_old_sample_expose),
+                    colorsel);
+  gtk_signal_connect(GTK_OBJECT (priv->cur_sample), "expose_event",
+                    GTK_SIGNAL_FUNC (color_cur_sample_expose),
+                    colorsel);
 
-  if (colorsel->wheel_buf != NULL)
-    g_free (colorsel->wheel_buf);
-  if (colorsel->value_buf != NULL)
-    g_free (colorsel->value_buf);
-  if (colorsel->sample_buf != NULL)
-    g_free (colorsel->sample_buf);
+  color_sample_setup_dnd (colorsel, priv->old_sample);
+  color_sample_setup_dnd (colorsel, priv->cur_sample);
 
-  (*GTK_OBJECT_CLASS (color_selection_parent_class)->finalize) (object);
+  gtk_widget_show_all (priv->sample_area);
 }
 
 static void
-gtk_color_selection_color_changed (GtkColorSelection *colorsel)
+color_sample_set_use_opacity (GtkColorSelection *colorsel)
 {
-  gtk_signal_emit (GTK_OBJECT (colorsel), color_selection_signals[COLOR_CHANGED]);
-}
+  ColorSelectionPrivate *priv;
 
-static void
-gtk_color_selection_update_input (GtkWidget *scale,
-                                  GtkWidget *entry,
-                                  gdouble    value)
-{
-  GtkAdjustment *adj;
-  gchar txt[32];
+  g_return_if_fail (colorsel != NULL);
 
-  if (scale != NULL)
-    {
-      adj = gtk_range_get_adjustment (GTK_RANGE (scale));
-      adj->value = (gfloat) value;
-      gtk_signal_handler_block_by_data (GTK_OBJECT (adj), (gpointer) scale);
-      gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed");
-      gtk_range_slider_update (GTK_RANGE (scale));
-      gtk_signal_handler_unblock_by_data (GTK_OBJECT (adj), (gpointer) scale);
-    }
+  priv = colorsel->private;
 
-  if (entry != NULL)
-    {
-      gtk_signal_handler_block_by_data (GTK_OBJECT (entry), (gpointer) entry);
-      sprintf (txt, "%.2f", value);
-      gtk_entry_set_text (GTK_ENTRY (entry), txt);
-      gtk_signal_handler_unblock_by_data (GTK_OBJECT (entry), (gpointer) entry);
-    }
+  color_sample_draw_samples (colorsel);
 }
 
+
+/*
+ *
+ * The palette area code
+ *
+ */
+#define CUSTOM_PALETTE_ENTRY_WIDTH   18
+#define CUSTOM_PALETTE_ENTRY_HEIGHT  18
+
 static void
-gtk_color_selection_update_inputs (GtkColorSelection *colorsel,
-                                   gint               inputs,
-                                   gint               which)
+palette_get_color (GtkWidget *drawing_area, gdouble *color)
 {
-  gint n;
+  gdouble *color_val;
+
+  g_return_if_fail (color != NULL);
 
-  switch (which)
+  color_val = gtk_object_get_data (GTK_OBJECT (drawing_area), "color_val");
+  if (color_val == NULL)
     {
-    case SCALE:
-      if ((inputs & RGB_INPUTS) != 0)
-       for (n = RED; n <= BLUE; n++)
-         gtk_color_selection_update_input (colorsel->scales[n], NULL,
-                                           colorsel->values[n]);
-      if ((inputs & HSV_INPUTS) != 0)
-       for (n = HUE; n <= VALUE; n++)
-         gtk_color_selection_update_input (colorsel->scales[n], NULL,
-                                           colorsel->values[n]);
-      if ((inputs & OPACITY_INPUTS) != 0)
-       gtk_color_selection_update_input(colorsel->scales[OPACITY], NULL,
-                                        colorsel->values[OPACITY]);
-      break;
-    case ENTRY:
-      if ((inputs & RGB_INPUTS) != 0)
-       for (n = RED; n <= BLUE; n++)
-         gtk_color_selection_update_input (NULL, colorsel->entries[n], colorsel->values[n]);
-      if ((inputs & HSV_INPUTS) != 0)
-       for (n = HUE; n <= VALUE; n++)
-         gtk_color_selection_update_input (NULL, colorsel->entries[n], colorsel->values[n]);
-      if ((inputs & OPACITY_INPUTS) != 0)
-       gtk_color_selection_update_input(NULL, colorsel->entries[OPACITY], colorsel->values[OPACITY]);
-      break;
-    default:
-      if ((inputs & RGB_INPUTS) != 0)
-       for (n = RED; n <= BLUE; n++)
-         gtk_color_selection_update_input (colorsel->scales[n], colorsel->entries[n],
-                                            colorsel->values[n]);
-      if ((inputs & HSV_INPUTS) != 0)
-       for (n = HUE; n <= VALUE; n++)
-         gtk_color_selection_update_input (colorsel->scales[n], colorsel->entries[n],
-                                            colorsel->values[n]);
-      if ((inputs & OPACITY_INPUTS) != 0)
-       gtk_color_selection_update_input(colorsel->scales[OPACITY], colorsel->entries[OPACITY],
-                                        colorsel->values[OPACITY]);
-      break;
+      /* Default to white for no good reason */
+      color[0] = 1.0;
+      color[1] = 1.0;
+      color[2] = 1.0;
+      color[3] = 1.0;
+      return;
     }
+
+  color[0] = color_val[0];
+  color[1] = color_val[1];
+  color[2] = color_val[2];
+  color[3] = 1.0;
 }
 
+#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
 static void
-gtk_color_selection_hsv_updater (GtkWidget *widget,
-                                 gpointer   data)
+palette_paint (GtkWidget *drawing_area, GdkRectangle *area, gpointer data)
 {
-  GtkColorSelection *colorsel;
-  GtkAdjustment *adj;
-  gdouble newvalue;
-  gint i, which = SCALE;
+  if (drawing_area->window == NULL)
+    return;
 
-  if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (widget)))
-    {
-      colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkColorSelection");
-      i = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (widget), value_index_key));
+  gdk_window_clear_area (drawing_area->window,
+                        area->x,
+                        area->y,
+                        area->width, 
+                        area->height);
 
-      if (GTK_IS_SCALE (widget))
-       {
-         adj = gtk_range_get_adjustment (GTK_RANGE (GTK_SCALE (widget)));
-         newvalue = (gdouble) adj->value;
-         which = ENTRY;
-       }
-      else
-       newvalue = (gdouble) atof (gtk_entry_get_text (GTK_ENTRY (widget)));
-
-      if (i == VALUE)
-       {
-         gtk_color_selection_draw_value_marker (colorsel);
-         colorsel->values[i] = newvalue;
+  if (GTK_WIDGET_HAS_FOCUS (drawing_area))
+    {
+      GdkGC *gc;
+      gdouble color[4];
 
-         HSV_TO_RGB ();
+      palette_get_color (drawing_area, color);
 
-         gtk_color_selection_draw_value_marker (colorsel);
-       }
+      if (INTENSITY (color[0], color[1], color[2]) > 0.5)
+       gc = drawing_area->style->black_gc;
       else
-       {
-         gtk_color_selection_draw_wheel_marker (colorsel);
-         colorsel->values[i] = newvalue;
+       gc = drawing_area->style->white_gc;
 
-         HSV_TO_RGB ();
-
-         gtk_color_selection_draw_wheel_marker (colorsel);
-         gtk_color_selection_draw_value_bar (colorsel, FALSE);
-       }
-
-      gtk_color_selection_draw_sample (colorsel, FALSE);
-      gtk_color_selection_color_changed (colorsel);
-      gtk_color_selection_update_inputs (colorsel, HSV_INPUTS, which);
-      gtk_color_selection_update_inputs (colorsel, RGB_INPUTS, BOTH);
+      gdk_draw_rectangle (drawing_area->window,
+                         gc, FALSE, 0, 0,
+                         drawing_area->allocation.width - 1,
+                         drawing_area->allocation.height - 1);
     }
 }
 
 static void
-gtk_color_selection_rgb_updater (GtkWidget *widget,
-                                 gpointer   data)
+palette_expose (GtkWidget *drawing_area, GdkEventExpose *event, gpointer data)
 {
-  GtkColorSelection *colorsel;
-  GtkAdjustment *adj;
-  gdouble newvalue;
-  gint i, which = SCALE;
-
-  if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (widget)))
-    {
-      colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkColorSelection");
-      i = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (widget), value_index_key));
-
-      if (GTK_IS_SCALE (widget))
-       {
-         adj = gtk_range_get_adjustment (GTK_RANGE (GTK_SCALE (widget)));
-         newvalue = (gdouble) adj->value;
-         which = ENTRY;
-       }
-      else
-       newvalue = (gdouble) atof (gtk_entry_get_text (GTK_ENTRY (widget)));
-
-      gtk_color_selection_draw_wheel_marker (colorsel);
-
-      colorsel->values[i] = newvalue;
-      RGB_TO_HSV ();
+  if (drawing_area->window == NULL)
+    return;
 
-      gtk_color_selection_draw_wheel_marker (colorsel);
-      gtk_color_selection_draw_value_bar (colorsel, FALSE);
-      gtk_color_selection_draw_sample (colorsel, FALSE);
-      gtk_color_selection_color_changed (colorsel);
-      gtk_color_selection_update_inputs (colorsel, RGB_INPUTS, which);
-      gtk_color_selection_update_inputs (colorsel, HSV_INPUTS, BOTH);
-    }
+  palette_paint (drawing_area, &(event->area), data);
 }
 
 static void
-gtk_color_selection_opacity_updater (GtkWidget *widget,
-                                     gpointer   data)
+palette_focus_in (GtkWidget *drawing_area, GdkEventFocus *event, gpointer data)
 {
-  GtkColorSelection *colorsel;
-  GtkAdjustment *adj;
+  ColorSelectionPrivate *priv;
 
-  colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkColorSelection");
-
-  if (GTK_IS_SCALE (widget))
-    {
-      adj = gtk_range_get_adjustment (GTK_RANGE (widget));
-      colorsel->values[OPACITY] = (gdouble) adj->value;
-      gtk_color_selection_update_input (NULL, colorsel->entries[OPACITY], colorsel->values[OPACITY]);
-    }
-  else
-    {
-      colorsel->values[OPACITY] = (gdouble) atof (gtk_entry_get_text (GTK_ENTRY (widget)));
-      gtk_color_selection_update_input (colorsel->scales[OPACITY], NULL, colorsel->values[OPACITY]);
-    }
+  if (drawing_area->window == NULL)
+    return;
 
-  gtk_color_selection_draw_sample (colorsel, FALSE);
-  gtk_color_selection_color_changed (colorsel);
+  priv = GTK_COLOR_SELECTION (data)->private;
+  priv->last_palette = drawing_area;
+  GTK_WIDGET_SET_FLAGS (drawing_area, GTK_HAS_FOCUS);
+  
+  gtk_widget_queue_clear_area (drawing_area, 0, 0, drawing_area->allocation.x, drawing_area->allocation.y);
 }
 
-void
-gtk_color_selection_set_opacity (GtkColorSelection *colorsel,
-                                 gint               use_opacity)
+static void
+palette_focus_out (GtkWidget *drawing_area, GdkEventFocus *event, gpointer data)
 {
-  g_return_if_fail (colorsel != NULL);
-
-  colorsel->use_opacity = use_opacity;
-
-  if (!use_opacity && GTK_WIDGET_VISIBLE (colorsel->scales[OPACITY]))
-    {
-      gtk_widget_hide (colorsel->opacity_label);
-      gtk_widget_hide (colorsel->scales[OPACITY]);
-      gtk_widget_hide (colorsel->entries[OPACITY]);
-    }
-  else if (use_opacity && !GTK_WIDGET_VISIBLE (colorsel->scales[OPACITY]))
-    {
-      gtk_widget_show (colorsel->opacity_label);
-      gtk_widget_show (colorsel->scales[OPACITY]);
-      gtk_widget_show (colorsel->entries[OPACITY]);
-    }
-
-  if (GTK_WIDGET_DRAWABLE (colorsel->sample_area))
-    gtk_color_selection_draw_sample (colorsel, FALSE);
+  GTK_WIDGET_UNSET_FLAGS (drawing_area, GTK_HAS_FOCUS);
+  gtk_widget_queue_clear_area (drawing_area, 0, 0, drawing_area->allocation.x, drawing_area->allocation.y);
 }
 
 static void
-gtk_color_selection_value_resize (GtkWidget *widget,
-                                  gpointer   data)
+palette_press (GtkWidget *drawing_area, GdkEventButton *event, gpointer data)
 {
-  GtkColorSelection *colorsel;
-
-  colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkColorSelection");
-  gtk_color_selection_draw_value_bar (colorsel, TRUE);
+  gtk_widget_grab_focus (drawing_area);
+  if (GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (drawing_area), "color_set")) != 0)
+    {
+      gdouble color[4];
+      palette_get_color (drawing_area, color);
+      gtk_color_selection_set_color (GTK_COLOR_SELECTION (data), color);
+    }
 }
 
 static void
-gtk_color_selection_wheel_resize (GtkWidget *widget,
-                                  gpointer   data)
+palette_draw (GtkWidget *drawing_area, GdkRectangle *area, gpointer data)
 {
-  GtkColorSelection *colorsel;
-
-  colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkColorSelection");
-  gtk_color_selection_draw_wheel (colorsel, TRUE);
+  palette_paint (drawing_area, area, data);
 }
 
 static void
-gtk_color_selection_sample_resize (GtkWidget *widget,
-                                   gpointer   data)
+palette_unset_color (GtkWidget *drawing_area)
 {
-  GtkColorSelection *colorsel;
+  if (GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (drawing_area), "color_set")) == 0)
+    return;
 
-  colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkColorSelection");
-  gtk_color_selection_draw_sample (colorsel, TRUE);
+  gtk_widget_reset_rc_styles (drawing_area);
+  gtk_object_set_data (GTK_OBJECT (drawing_area), "color_set", GINT_TO_POINTER (0));
 }
 
 static void
-gtk_color_selection_drag_begin (GtkWidget      *widget,
-                               GdkDragContext *context,
-                               gpointer        data)
+palette_drag_begin (GtkWidget      *widget,
+                   GdkDragContext *context,
+                   gpointer        data)
 {
   GtkColorSelection *colorsel = data;
+  ColorSelectionPrivate *priv;
   GtkWidget *window;
   gdouble colors[4];
   GdkColor bg;
 
+  priv = colorsel->private;
   window = gtk_window_new (GTK_WINDOW_POPUP);
   gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
   gtk_widget_set_usize (window, 48, 32);
@@ -942,7 +671,7 @@ gtk_color_selection_drag_begin (GtkWidget      *widget,
                            window,
                            (GtkDestroyNotify) gtk_widget_destroy);
 
-  gtk_color_selection_get_color (colorsel, colors);
+  palette_get_color (widget, colors);
   bg.red = 0xffff * colors[0];
   bg.green = 0xffff * colors[1];
   bg.blue = 0xffff * colors[2];
@@ -954,803 +683,1157 @@ gtk_color_selection_drag_begin (GtkWidget      *widget,
 }
 
 static void
-gtk_color_selection_drag_end (GtkWidget      *widget,
-                             GdkDragContext *context,
-                             gpointer        data)
+palette_drag_handle (GtkWidget        *widget,
+                    GdkDragContext   *context,
+                    GtkSelectionData *selection_data,
+                    guint             info,
+                    guint             time,
+                    gpointer          data)
+{
+  guint16 vals[4];
+  gdouble colsrc[4];
+
+  palette_get_color (widget, colsrc);
+
+  vals[0] = colsrc[COLORSEL_RED] * 0xffff;
+  vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
+  vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
+  vals[3] = 0xffff;
+
+  gtk_selection_data_set (selection_data,
+                         gdk_atom_intern ("application/x-color", FALSE),
+                         16, (guchar *)vals, 8);
+}
+
+static void
+palette_set_color (GtkWidget *drawing_area, GtkColorSelection *colorsel, gdouble *color)
+{
+  GtkRcStyle *rc_style;
+  gdouble *new_color = g_new (double, 4);
+  gdouble *old_color;
+
+  rc_style = gtk_rc_style_new ();
+  rc_style->bg[GTK_STATE_NORMAL].red = color[0]*65535;
+  rc_style->bg[GTK_STATE_NORMAL].green = color[1]*65535;
+  rc_style->bg[GTK_STATE_NORMAL].blue = color[2]*65535;
+  rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_BG;
+  gtk_rc_style_ref (rc_style);
+  gtk_widget_modify_style (drawing_area, rc_style);
+
+  if (GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (drawing_area), "color_set")) == 0)
+    {
+      static const GtkTargetEntry targets[] = {
+       { "application/x-color", 0 }
+      };
+      gtk_drag_source_set (drawing_area,
+                          GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
+                          targets, 1,
+                          GDK_ACTION_COPY | GDK_ACTION_MOVE);
+
+      gtk_signal_connect (GTK_OBJECT (drawing_area),
+                         "drag_begin",
+                         GTK_SIGNAL_FUNC (palette_drag_begin),
+                         colorsel);
+      gtk_signal_connect (GTK_OBJECT (drawing_area),
+                         "drag_data_get",
+                         GTK_SIGNAL_FUNC (palette_drag_handle),
+                         colorsel);
+
+      gtk_object_set_data (GTK_OBJECT (drawing_area), "color_set", GINT_TO_POINTER (1));
+    }
+  else
+    {
+      old_color = (gdouble *) gtk_object_get_data (GTK_OBJECT (drawing_area), "color_val");
+      if (old_color)
+       {
+         g_free (old_color);
+       }
+    }
+  new_color[0] = color[0];
+  new_color[1] = color[1];
+  new_color[2] = color[2];
+  new_color[3] = 1.0;
+
+  gtk_object_set_data (GTK_OBJECT (drawing_area), "color_val", new_color);
+}
+
+static void
+palette_drag_end (GtkWidget      *widget,
+                 GdkDragContext *context,
+                 gpointer        data)
 {
   gtk_object_set_data (GTK_OBJECT (widget), "gtk-color-selection-drag-window", NULL);
 }
 
 static void
-gtk_color_selection_drop_handle (GtkWidget        *widget, 
-                                GdkDragContext   *context,
-                                gint              x,
-                                gint              y,
-                                GtkSelectionData *selection_data,
-                                guint             info,
-                                guint             time,
-                                gpointer          data)
+palette_drop_handle (GtkWidget        *widget,
+                    GdkDragContext   *context,
+                    gint              x,
+                    gint              y,
+                    GtkSelectionData *selection_data,
+                    guint             info,
+                    guint             time,
+                    gpointer          data)
 {
-  GtkColorSelection *colorsel = data;
   guint16 *vals;
-  gdouble colors[4];
-
-  /* This is currently a guint16 array of the format:
-     R
-     G
-     B
-     opacity
-  */
+  gdouble color[4];
 
   if (selection_data->length < 0)
     return;
 
-  if ((selection_data->format != 16) || 
+  if ((selection_data->format != 16) ||
       (selection_data->length != 8))
     {
       g_warning ("Received invalid color data\n");
       return;
     }
-  
+
   vals = (guint16 *)selection_data->data;
 
-  colors[0] = (gdouble)vals[0] / 0xffff;
-  colors[1] = (gdouble)vals[1] / 0xffff;
-  colors[2] = (gdouble)vals[2] / 0xffff;
-  colors[3] = (gdouble)vals[3] / 0xffff;
-  
-  gtk_color_selection_set_color(colorsel, colors);
+  color[0] = (gdouble)vals[0] / 0xffff;
+  color[1] = (gdouble)vals[1] / 0xffff;
+  color[2] = (gdouble)vals[2] / 0xffff;
+  color[3] = (gdouble)vals[3] / 0xffff;
+  palette_set_color (widget, GTK_COLOR_SELECTION (data), color);
+  gtk_color_selection_set_color (GTK_COLOR_SELECTION (data), color);
+}
+
+static int
+palette_activate (GtkWidget        *widget,
+                 GdkEventKey      *event,
+                 gpointer          data)
+{
+  GtkColorSelection *colorsel = data;
+  ColorSelectionPrivate *priv;
+
+  if ((event->keyval == ' ') || (event->keyval == GDK_Return))
+    {
+      priv = colorsel->private;
+      palette_set_color (widget, GTK_COLOR_SELECTION (data), priv->color);
+    }
+
+  return TRUE;
 }
 
-static void
-gtk_color_selection_drag_handle (GtkWidget        *widget, 
-                                GdkDragContext   *context,
-                                GtkSelectionData *selection_data,
-                                guint             info,
-                                guint             time,
-                                gpointer          data)
+static GtkWidget *
+palette_new (GtkColorSelection *colorsel)
 {
-  GtkColorSelection *colorsel = data;
-  guint16 vals[4];
-  gdouble colors[4];
+  GtkWidget *retval;
+  
+  static const GtkTargetEntry targets[] = {
+    { "application/x-color", 0 }
+  };
 
-  gtk_color_selection_get_color(colorsel, colors);
+  retval = gtk_drawing_area_new ();
+  gtk_object_set_data (GTK_OBJECT (retval), "color_set", GINT_TO_POINTER (0)); 
+  gtk_widget_set_events (retval, GDK_BUTTON_PRESS_MASK | GDK_EXPOSURE_MASK);
+
+  GTK_WIDGET_SET_FLAGS (retval, GTK_CAN_FOCUS);
+  gtk_signal_connect (GTK_OBJECT (retval), "focus_in_event", palette_focus_in, colorsel);
+  gtk_signal_connect (GTK_OBJECT (retval), "focus_out_event", palette_focus_out, colorsel);
+  gtk_signal_connect (GTK_OBJECT (retval), "draw", palette_draw, colorsel);
+  gtk_signal_connect (GTK_OBJECT (retval), "expose_event", palette_expose, colorsel);
+  gtk_signal_connect (GTK_OBJECT (retval), "button_press_event", palette_press, colorsel);
+
+  gtk_drag_dest_set (retval,
+                    GTK_DEST_DEFAULT_HIGHLIGHT |
+                    GTK_DEST_DEFAULT_MOTION |
+                    GTK_DEST_DEFAULT_DROP,
+                    targets, 1,
+                    GDK_ACTION_COPY);
+
+  gtk_signal_connect (GTK_OBJECT (retval), "drag_end", palette_drag_end, NULL);
+  gtk_signal_connect (GTK_OBJECT (retval), "drag_data_received", palette_drop_handle, colorsel);
+  gtk_signal_connect (GTK_OBJECT (retval), "key_press_event", GTK_SIGNAL_FUNC (palette_activate), colorsel);
+
+  return retval;
+}
 
-  vals[0] = colors[0] * 0xffff;
-  vals[1] = colors[1] * 0xffff;
-  vals[2] = colors[2] * 0xffff;
-  vals[3] = colorsel->use_opacity ? colors[3] * 0xffff : 0xffff;
 
-  gtk_selection_data_set (selection_data,
-                         gdk_atom_intern ("application/x-color", FALSE),
-                         16, (guchar *)vals, 8);
-}
+/*
+ *
+ * The actual GtkColorSelection widget
+ *
+ */
 
 static void
-gtk_color_selection_draw_wheel_marker (GtkColorSelection *colorsel)
+initialize_cursor ()
 {
-  gint xpos, ypos;
+  GdkColor fg, bg;
+
+  GdkPixmap *pixmap =
+    gdk_bitmap_create_from_data (NULL,
+                                dropper_bits,
+                                DROPPER_WIDTH, DROPPER_HEIGHT);
+  GdkPixmap *mask =
+    gdk_bitmap_create_from_data (NULL,
+                                dropper_mask,
+                                DROPPER_WIDTH, DROPPER_HEIGHT);
 
-  gdk_gc_set_function (colorsel->wheel_gc, GDK_INVERT);
+  gdk_color_white (gdk_colormap_get_system (), &bg);
+  gdk_color_black (gdk_colormap_get_system (), &fg);
 
-  xpos = (gint) ((-(gdouble) (colorsel->wheel_area->allocation.width) / 2.0) *
-                colorsel->values[SATURATION] * cos (DEGTORAD ((colorsel->values[HUE] - 90)))) +
-                 (colorsel->wheel_area->allocation.width >> 1) - 4;
-  ypos = (gint) (((gdouble) (colorsel->wheel_area->allocation.height) / 2.0) *
-                colorsel->values[SATURATION] * sin (DEGTORAD ((colorsel->values[HUE] - 90)))) +
-                 (colorsel->wheel_area->allocation.height >> 1) - 4;
+  picker_cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg, DROPPER_X_HOT ,DROPPER_Y_HOT);
+
+  gdk_pixmap_unref (pixmap);
+  gdk_pixmap_unref (mask);
 
-  gdk_draw_arc (colorsel->wheel_area->window, colorsel->wheel_gc, FALSE, xpos, ypos, 8, 8, 0, 360 * 64);
 }
 
 static void
-gtk_color_selection_draw_value_marker (GtkColorSelection *colorsel)
+grab_color_at_mouse (GtkWidget *button, int x_root, int y_root, gpointer data)
 {
-  gint y;
-
-  gdk_gc_set_function (colorsel->value_gc, GDK_INVERT);
+  GdkImage *image;
+  guint32 pixel;
+  GdkVisual *visual;
+  GtkColorSelection *colorsel = data;
+  ColorSelectionPrivate *priv;
+  GdkColormap *colormap = gdk_colormap_get_system ();
+  XColor xcolor;
+
+  priv = colorsel->private;
+
+  image = gdk_image_get (GDK_ROOT_PARENT (), x_root, y_root, 1, 1);
+  pixel = gdk_image_get_pixel (image, 0, 0);
+  visual = gdk_colormap_get_visual (colormap);
+
+  switch (visual->type) {
+  case GDK_VISUAL_DIRECT_COLOR:
+  case GDK_VISUAL_TRUE_COLOR:
+    priv->color[COLORSEL_RED] = (double)((pixel & visual->red_mask)>>visual->red_shift)/((1<<visual->red_prec) - 1);
+    priv->color[COLORSEL_GREEN] = (double)((pixel & visual->green_mask)>>visual->green_shift)/((1<<visual->green_prec) - 1);
+    priv->color[COLORSEL_BLUE] = (double)((pixel & visual->blue_mask)>>visual->blue_shift)/((1<<visual->blue_prec) - 1);
+    break;
+  case GDK_VISUAL_STATIC_GRAY:
+  case GDK_VISUAL_GRAYSCALE:
+    priv->color[COLORSEL_RED] = (double)pixel/((1<<visual->depth) - 1);
+    priv->color[COLORSEL_GREEN] = (double)pixel/((1<<visual->depth) - 1);
+    priv->color[COLORSEL_BLUE] = (double)pixel/((1<<visual->depth) - 1);
+    break;
+  case GDK_VISUAL_STATIC_COLOR:
+    xcolor.pixel = pixel;
+    XQueryColor (GDK_DISPLAY (), GDK_COLORMAP_XCOLORMAP (colormap), &xcolor);
+    priv->color[COLORSEL_RED] = xcolor.red/65535.0;
+    priv->color[COLORSEL_GREEN] = xcolor.green/65535.0;
+    priv->color[COLORSEL_BLUE] = xcolor.blue/65535.0;
+    break;
+  case GDK_VISUAL_PSEUDO_COLOR:
+    priv->color[COLORSEL_RED] = colormap->colors[pixel].red/(double)0xffffff;
+    priv->color[COLORSEL_GREEN] = colormap->colors[pixel].green/(double)0xffffff;
+    priv->color[COLORSEL_BLUE] = colormap->colors[pixel].blue/(double)0xffffff;
+    break;
+  default:
+    g_assert_not_reached ();
+    break;
+  }
+
+  gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
+                 priv->color[COLORSEL_GREEN],
+                 priv->color[COLORSEL_BLUE],
+                 &priv->color[COLORSEL_HUE],
+                 &priv->color[COLORSEL_SATURATION],
+                 &priv->color[COLORSEL_VALUE]);
+  update_color (colorsel);
+}
 
-  y = (gint) ((gdouble) (colorsel->value_area->allocation.height) * (1.0 - colorsel->values[VALUE]));
-  gdk_draw_line (colorsel->value_area->window, colorsel->value_gc,
-                 0, y, colorsel->value_area->allocation.width, y);
+static void
+mouse_motion (GtkWidget *button, GdkEventMotion *event, gpointer data)
+{
+  grab_color_at_mouse (button, event->x_root, event->y_root, data); 
 }
 
 static void
-gtk_color_selection_update_value (GtkColorSelection *colorsel,
-                                  gint               y)
+mouse_release (GtkWidget *button, GdkEventButton *event, gpointer data)
 {
-  gtk_color_selection_draw_value_marker (colorsel);
+  GtkColorSelection *colorsel = data;
+  ColorSelectionPrivate *priv;
+  priv = colorsel->private;
 
-  if (y < 0)
-    y = 0;
-  else if (y > colorsel->value_area->allocation.height - 1)
-    y = colorsel->value_area->allocation.height - 1;
+  gtk_signal_disconnect_by_func (GTK_OBJECT (button), mouse_motion, data);
+  gtk_signal_disconnect_by_func (GTK_OBJECT (button), mouse_release, data);
 
-  colorsel->values[VALUE] = 1.0 - (gdouble) y / (gdouble) (colorsel->value_area->allocation.height);
+  grab_color_at_mouse (button, event->x_root, event->y_root, data);
+  gdk_pointer_ungrab (0);
+}
 
-  HSV_TO_RGB ();
+/* Helper Functions */
+static void
+mouse_press (GtkWidget *button, GdkEventButton *event, gpointer data)
+{
+  GtkColorSelection *colorsel = data;
+  ColorSelectionPrivate *priv;
+  priv = colorsel->private;
 
-  gtk_color_selection_draw_value_marker (colorsel);
-  gtk_color_selection_draw_sample (colorsel, FALSE);
-  gtk_color_selection_update_input (colorsel->scales[VALUE], colorsel->entries[VALUE],
-                                   colorsel->values[VALUE]);
-  gtk_color_selection_update_inputs (colorsel, RGB_INPUTS, BOTH);
+  gtk_signal_connect (GTK_OBJECT (button), "motion_notify_event", mouse_motion, data);
+  gtk_signal_connect (GTK_OBJECT (button), "button_release_event", mouse_release, data);
+  gtk_signal_disconnect_by_func (GTK_OBJECT (button), mouse_press, data); 
 }
 
+/* when the button is clicked */
 static void
-gtk_color_selection_update_wheel (GtkColorSelection *colorsel,
-                                  gint               x,
-                                  gint               y)
+get_screen_color (GtkWidget *button)
 {
-  gdouble wid, heig;
-  gint res;
+  GtkColorSelection *colorsel = gtk_object_get_data (GTK_OBJECT (button), "COLORSEL");
+  ColorSelectionPrivate *priv = colorsel->private; 
+
+  if (picker_cursor == NULL)
+    {
+      initialize_cursor ();
+    }
 
-  gtk_color_selection_draw_wheel_marker (colorsel);
+  /* Why do we do this? Because the "clicked" signal will be emitted after the "button_released"
+     signal. We don't want to do this stuff again, though, or else it will get trapped here. So, 
+     priv->moving_dropper is initialized to FALSE at the initialization of the colorselector, 
+     it is initialized to true when we start waiting for the user to click the the dropper on a 
+     color, and whenver it is true when this function starts to execute, we set it to false. */
+  if (priv->moving_dropper == FALSE)
+    {
+      priv->moving_dropper = TRUE;
+      gtk_signal_connect (GTK_OBJECT (button), "button_press_event", mouse_press, colorsel); 
+
+      gdk_pointer_grab (button->window,
+                       FALSE,
+                       GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK,
+                       NULL,
+                       picker_cursor,
+                       0);
+    }
+  else
+    {
+      priv->moving_dropper = FALSE; 
+    }
+}
 
-  wid = (gdouble) (colorsel->wheel_area->allocation.width) / 2.0;
-  heig = (gdouble) (colorsel->wheel_area->allocation.height) / 2.0;
+void
+hex_changed (GtkWidget *hex_entry, gpointer data)
+{
+  GtkColorSelection *colorsel;
+  ColorSelectionPrivate *priv;
+  GdkColor color;
+  gchar *text;
 
-  res = gtk_color_selection_eval_wheel (x, y, wid, heig, &colorsel->values[HUE],
-                                        &colorsel->values[SATURATION]);
+  colorsel = GTK_COLOR_SELECTION (data);
+  priv = colorsel->private;
 
-  HSV_TO_RGB ();
+  if (priv->changing)
+    return;
 
-  gtk_color_selection_draw_wheel_marker (colorsel);
-  gtk_color_selection_draw_value_bar (colorsel, FALSE);
-  gtk_color_selection_draw_sample (colorsel, FALSE);
-  gtk_color_selection_update_inputs (colorsel, RGB_INPUTS | HSV_INPUTS, BOTH);
+  text = gtk_editable_get_chars (GTK_EDITABLE (priv->hex_entry), 0, -1);
+  if (gdk_color_parse (text, &color))
+    {
+      priv->color[COLORSEL_RED] = CLAMP (color.red/65280.0, 0.0, 1.0);
+      priv->color[COLORSEL_GREEN] = CLAMP (color.green/65280.0, 0.0, 1.0);
+      priv->color[COLORSEL_BLUE] = CLAMP (color.blue/65280.0, 0.0, 1.0);
+      gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
+                     priv->color[COLORSEL_GREEN],
+                     priv->color[COLORSEL_BLUE],
+                     &priv->color[COLORSEL_HUE],
+                     &priv->color[COLORSEL_SATURATION],
+                     &priv->color[COLORSEL_VALUE]);
+      update_color (colorsel);
+    }
+  g_free (text);
 }
 
-static gint
-gtk_color_selection_value_timeout (GtkColorSelection *colorsel)
+void
+hsv_changed (GtkWidget *hsv, gpointer data)
 {
-  gint x, y;
-  
-  GDK_THREADS_ENTER ();
-  
-  gdk_window_get_pointer (colorsel->value_area->window, &x, &y, NULL);
-  gtk_color_selection_update_value (colorsel, y);
-  gtk_color_selection_color_changed (colorsel);
+  GtkColorSelection *colorsel;
+  ColorSelectionPrivate *priv;
 
-  GDK_THREADS_LEAVE ();
+  colorsel = GTK_COLOR_SELECTION (data);
+  priv = colorsel->private;
 
-  return (TRUE);
+  if (priv->changing)
+    return;
+
+  gtk_hsv_get_color (GTK_HSV (hsv),
+                    &priv->color[COLORSEL_HUE],
+                    &priv->color[COLORSEL_SATURATION],
+                    &priv->color[COLORSEL_VALUE]);
+  gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
+                 priv->color[COLORSEL_SATURATION],
+                 priv->color[COLORSEL_VALUE],
+                 &priv->color[COLORSEL_RED],
+                 &priv->color[COLORSEL_GREEN],
+                 &priv->color[COLORSEL_BLUE]);
+  update_color (colorsel);
 }
 
-static gint
-gtk_color_selection_value_events (GtkWidget *area,
-                                  GdkEvent  *event)
+void
+adjustment_changed (GtkAdjustment *adjustment, gpointer data)
 {
   GtkColorSelection *colorsel;
-  gint y;
+  ColorSelectionPrivate *priv;
 
-  colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (area), "_GtkColorSelection");
+  colorsel = GTK_COLOR_SELECTION (gtk_object_get_data (GTK_OBJECT (adjustment), "COLORSEL"));
+  priv = colorsel->private;
 
-  if (colorsel->value_gc == NULL)
-    colorsel->value_gc = gdk_gc_new (colorsel->value_area->window);
+  if (priv->changing)
+    return;
 
-  switch (event->type)
+  switch (GPOINTER_TO_INT (data))
     {
-    case GDK_MAP:
-      gtk_color_selection_draw_value_bar (colorsel, FALSE);
-      gtk_color_selection_draw_value_marker (colorsel);
+    case COLORSEL_SATURATION:
+    case COLORSEL_VALUE:
+      priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
+      gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
+                     priv->color[COLORSEL_SATURATION],
+                     priv->color[COLORSEL_VALUE],
+                     &priv->color[COLORSEL_RED],
+                     &priv->color[COLORSEL_GREEN],
+                     &priv->color[COLORSEL_BLUE]);
       break;
-    case GDK_EXPOSE:
-      gtk_color_selection_draw_value_marker (colorsel);
+    case COLORSEL_HUE:
+      priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 360;
+      gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
+                     priv->color[COLORSEL_SATURATION],
+                     priv->color[COLORSEL_VALUE],
+                     &priv->color[COLORSEL_RED],
+                     &priv->color[COLORSEL_GREEN],
+                     &priv->color[COLORSEL_BLUE]);
       break;
-    case GDK_BUTTON_PRESS:
-      gtk_grab_add (area);
-      gtk_color_selection_update_value (colorsel, event->button.y);
-      gtk_color_selection_color_changed (colorsel);
-      break;
-    case GDK_BUTTON_RELEASE:
-      gtk_grab_remove (area);
-      if (colorsel->timer_active)
-       gtk_timeout_remove (colorsel->timer_tag);
-      colorsel->timer_active = FALSE;
-
-      y = event->button.y;
-      if (event->button.window != area->window)
-       gdk_window_get_pointer (area->window, NULL, &y, NULL);
-
-      gtk_color_selection_update_value (colorsel, y);
-      gtk_color_selection_color_changed (colorsel);
-      break;
-    case GDK_MOTION_NOTIFY:
-      /* Even though we select BUTTON_MOTION_MASK, we seem to need
-       * to occasionally get events without buttons pressed.
-       */
-      if (!(event->motion.state &
-           (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)))
-       return FALSE;
-      
-      y = event->motion.y;
-
-      if (event->motion.is_hint || (event->motion.window != area->window))
-       gdk_window_get_pointer (area->window, NULL, &y, NULL);
-
-      switch (colorsel->policy)
-       {
-       case GTK_UPDATE_CONTINUOUS:
-         gtk_color_selection_update_value (colorsel, y);
-         gtk_color_selection_color_changed (colorsel);
-         break;
-       case GTK_UPDATE_DELAYED:
-         if (colorsel->timer_active)
-           gtk_timeout_remove (colorsel->timer_tag);
-
-         colorsel->timer_tag = gtk_timeout_add (TIMER_DELAY,
-                                                (GtkFunction) gtk_color_selection_value_timeout,
-                                                (gpointer) colorsel);
-         colorsel->timer_active = TRUE;
-         break;
-       default:
-         break;
-       }
+    case COLORSEL_RED:
+    case COLORSEL_GREEN:
+    case COLORSEL_BLUE:
+      priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
+
+      gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
+                     priv->color[COLORSEL_GREEN],
+                     priv->color[COLORSEL_BLUE],
+                     &priv->color[COLORSEL_HUE],
+                     &priv->color[COLORSEL_SATURATION],
+                     &priv->color[COLORSEL_VALUE]);
       break;
     default:
+      priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
       break;
     }
-
-  return (FALSE);
+  update_color (colorsel);
 }
 
-static gint
-gtk_color_selection_wheel_timeout (GtkColorSelection *colorsel)
+void 
+opacity_entry_changed (GtkWidget *opacity_entry, gpointer data)
 {
-  gint x, y;
+  GtkColorSelection *colorsel;
+  ColorSelectionPrivate *priv;
+  GtkAdjustment *adj;
+  gchar *text;
 
-  GDK_THREADS_ENTER ();
+  colorsel = GTK_COLOR_SELECTION (data);
+  priv = colorsel->private;
+  
+  if (priv->changing)
+    return;
 
-  gdk_window_get_pointer (colorsel->wheel_area->window, &x, &y, NULL);
-  gtk_color_selection_update_wheel (colorsel, x, y);
-  gtk_color_selection_color_changed (colorsel);
+  text = gtk_editable_get_chars (GTK_EDITABLE (priv->opacity_entry), 0, -1);
+  adj = gtk_range_get_adjustment (GTK_RANGE (priv->opacity_slider));
+  gtk_adjustment_set_value (adj, g_strtod (text, NULL)); 
 
-  GDK_THREADS_LEAVE ();
+  update_color (colorsel);
 
-  return (TRUE);
+  g_free (text);
 }
 
-static gint
-gtk_color_selection_wheel_events (GtkWidget *area,
-                                  GdkEvent  *event)
+static void
+widget_focus_in (GtkWidget *drawing_area, GdkEventFocus *event, gpointer data)
+     /* This signal is connected to by all of the widgets except the "Set Color" button */
+     /* This will let you add a color to the currently selected palette */
 {
-  GtkColorSelection *colorsel;
-  gint x, y;
-
-  colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (area), "_GtkColorSelection");
-  
-  if (colorsel->wheel_gc == NULL)
-    colorsel->wheel_gc = gdk_gc_new (colorsel->wheel_area->window);
-  if (colorsel->sample_gc == NULL)
-    colorsel->sample_gc = gdk_gc_new (colorsel->sample_area->window);
-  if (colorsel->value_gc == NULL)
-    colorsel->value_gc = gdk_gc_new (colorsel->value_area->window);
-  
-  switch (event->type)
-    {
-    case GDK_MAP:
-      gtk_color_selection_draw_wheel (colorsel, TRUE);
-      gtk_color_selection_draw_wheel_marker (colorsel);
-      gtk_color_selection_draw_sample (colorsel, TRUE);
-      break;
-    case GDK_EXPOSE:
-      gtk_color_selection_draw_wheel_marker (colorsel);
-      gtk_color_selection_draw_wheel_frame (colorsel);
-      break;
-    case GDK_BUTTON_PRESS:
-      gtk_grab_add (area);
-      gtk_color_selection_update_wheel (colorsel, event->button.x, event->button.y);
-      gtk_color_selection_color_changed (colorsel);
-      break;
-    case GDK_BUTTON_RELEASE:
-      gtk_grab_remove (area);
-      if (colorsel->timer_active)
-       gtk_timeout_remove (colorsel->timer_tag);
-      colorsel->timer_active = FALSE;
-
-      x = event->button.x;
-      y = event->button.y;
-
-      if (event->button.window != area->window)
-       gdk_window_get_pointer (area->window, &x, &y, NULL);
+  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
+  ColorSelectionPrivate *priv;
 
-      gtk_color_selection_update_wheel (colorsel, x, y);
-      gtk_color_selection_color_changed (colorsel);
-      break;
-    case GDK_MOTION_NOTIFY:
-      /* Even though we select BUTTON_MOTION_MASK, we seem to need
-       * to occasionally get events without buttons pressed.
-       */
-      if (!(event->motion.state &
-           (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)))
-       return FALSE;
-      
-      x = event->motion.x;
-      y = event->motion.y;
-
-      if (event->motion.is_hint || (event->motion.window != area->window))
-       gdk_window_get_pointer (area->window, &x, &y, NULL);
-
-      switch (colorsel->policy)
-       {
-       case GTK_UPDATE_CONTINUOUS:
-         gtk_color_selection_update_wheel (colorsel, x, y);
-         gtk_color_selection_color_changed (colorsel);
-         break;
-       case GTK_UPDATE_DELAYED:
-         if (colorsel->timer_active)
-           gtk_timeout_remove (colorsel->timer_tag);
-         colorsel->timer_tag = gtk_timeout_add (TIMER_DELAY,
-                                                (GtkFunction) gtk_color_selection_wheel_timeout,
-                                                (gpointer) colorsel);
-         colorsel->timer_active = TRUE;
-         break;
-       default:
-         break;
-       }
-      break;
-    default:
-      break;
-    }
+  priv = colorsel->private;
 
-  return (FALSE);
+  priv->last_palette = NULL;
 }
 
+
 static void
-gtk_color_selection_draw_value_bar (GtkColorSelection *colorsel,
-                                    gint               resize)
+make_label_spinbutton (GtkColorSelection *colorsel,
+                      GtkWidget **spinbutton,
+                      gchar *text,
+                      GtkWidget *table,
+                      gint i, gint j,
+                      gint channel_type)
 {
-  gint x, y, wid, heig, n;
-  gdouble sv, v;
+  GtkWidget *label;
+  GtkAdjustment *adjust;
 
-  wid = colorsel->value_area->allocation.width;
-  heig = colorsel->value_area->allocation.height;
-
-  if (resize || !colorsel->value_buf)
+  if (channel_type == COLORSEL_HUE)
     {
-      g_free (colorsel->value_buf);
-      colorsel->value_buf = g_new0 (guchar, 3 * wid);
+      adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 360.0, 1.0, 1.0, 1.0));
     }
-
-  v = 1.0;
-  sv = 1.0 / (gdouble) MAX (heig - 1, 0);
-
-  for (y = 0; y < heig; y++)
+  else
     {
-      gdouble c[3];
-      guchar rc[3];
-      gint i = 0;
-
-      gtk_color_selection_hsv_to_rgb (colorsel->values[HUE],
-                                     colorsel->values[SATURATION],
-                                     v,
-                                      &c[0], &c[1], &c[2]);
-
-      for (n = 0; n < 3; n++)
-       rc[n] = (guchar) (255.0 * c[n]);
-
-      for (x = 0; x < wid; x++)
-       {
-         for (n = 0; n < 3; n++)
-           colorsel->value_buf[i++] = rc[n];
-       }
-
-      gtk_preview_draw_row (GTK_PREVIEW (colorsel->value_area), colorsel->value_buf, 0, y, wid);
-      v -= sv;
+      adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 1.0));
     }
+  gtk_object_set_data (GTK_OBJECT (adjust), "COLORSEL", colorsel);
+  *spinbutton = gtk_spin_button_new (adjust, 10.0, 0);
+  gtk_signal_connect (GTK_OBJECT (*spinbutton), "focus_in_event", widget_focus_in, colorsel);
+  gtk_signal_connect (GTK_OBJECT (adjust), "value_changed", adjustment_changed, GINT_TO_POINTER (channel_type));
+  label = gtk_label_new (text);
+  gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label, i, i+1, j, j+1);
+  gtk_table_attach_defaults (GTK_TABLE (table), *spinbutton, i+1, i+2, j, j+1);
 
-  gtk_widget_queue_draw (colorsel->value_area);
 }
 
 static void
-gtk_color_selection_draw_wheel_frame (GtkColorSelection *colorsel)
+make_palette_frame (GtkColorSelection *colorsel, GtkWidget *table, gint i, gint j)
 {
-  GtkStyle *style;
-  gint w, h;
-
-  style = gtk_widget_get_style (colorsel->wheel_area);
-
-  w = colorsel->wheel_area->allocation.width;
-  h = colorsel->wheel_area->allocation.height;
+  GtkWidget *frame;
+  ColorSelectionPrivate *priv;
 
-  gdk_draw_arc (colorsel->wheel_area->window, style->black_gc,
-               FALSE, 1, 1, w - 1, h - 1, 30 * 64, 180 * 64);
-  gdk_draw_arc (colorsel->wheel_area->window, style->mid_gc[GTK_STATE_NORMAL],
-               FALSE, 0, 0, w, h, 30 * 64, 180 * 64);
-
-  gdk_draw_arc (colorsel->wheel_area->window, style->bg_gc[GTK_STATE_NORMAL],
-               FALSE, 1, 1, w - 1, h - 1, 210 * 64, 180 * 64);
-  gdk_draw_arc (colorsel->wheel_area->window, style->light_gc[GTK_STATE_NORMAL],
-               FALSE, 0, 0, w, h, 210 * 64, 180 * 64);
+  priv = colorsel->private;
+  frame = gtk_frame_new (NULL);
+  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+  priv->custom_palette[i][j] = palette_new (colorsel);
+  gtk_widget_set_usize (priv->custom_palette[i][j], CUSTOM_PALETTE_ENTRY_WIDTH, CUSTOM_PALETTE_ENTRY_HEIGHT);
+  gtk_container_add (GTK_CONTAINER (frame), priv->custom_palette[i][j]);
+  gtk_table_attach_defaults (GTK_TABLE (table), frame, i, i+1, j, j+1);
 }
 
 static void
-gtk_color_selection_draw_wheel (GtkColorSelection *colorsel,
-                                gint               resize)
+update_color (GtkColorSelection *colorsel)
 {
-  gint x, y, i, wid, heig, n;
-  gdouble cx, cy, h, s, c[3];
-  guchar bg[3];
-  GtkStyle *style = gtk_widget_get_style (colorsel->wheel_area);
-
-  wid = colorsel->wheel_area->allocation.width;
-  heig = colorsel->wheel_area->allocation.height;
-
-  if (resize)
-    {
-      if (colorsel->wheel_buf != NULL)
-       g_free (colorsel->wheel_buf);
-
-      colorsel->wheel_buf = g_new(guchar, 3 * wid);
-    }
+  ColorSelectionPrivate *priv = colorsel->private;
+  gchar entryval[12];
+  gchar opacity_text[32];
+  gchar *ptr;
+  priv->changing = TRUE;
+  color_sample_draw_samples (colorsel);
+
+  gtk_hsv_set_color (GTK_HSV (priv->triangle_colorsel),
+                    priv->color[COLORSEL_HUE],
+                    priv->color[COLORSEL_SATURATION],
+                    priv->color[COLORSEL_VALUE]);
+  gtk_adjustment_set_value (gtk_spin_button_get_adjustment
+                           (GTK_SPIN_BUTTON (priv->hue_spinbutton)),
+                           priv->color[COLORSEL_HUE] * 360);
+  gtk_adjustment_set_value (gtk_spin_button_get_adjustment
+                           (GTK_SPIN_BUTTON (priv->sat_spinbutton)),
+                           priv->color[COLORSEL_SATURATION] * 255);
+  gtk_adjustment_set_value (gtk_spin_button_get_adjustment
+                           (GTK_SPIN_BUTTON (priv->val_spinbutton)),
+                           priv->color[COLORSEL_VALUE] * 255);
+  gtk_adjustment_set_value (gtk_spin_button_get_adjustment
+                           (GTK_SPIN_BUTTON (priv->red_spinbutton)),
+                           priv->color[COLORSEL_RED] * 255);
+  gtk_adjustment_set_value (gtk_spin_button_get_adjustment
+                           (GTK_SPIN_BUTTON (priv->green_spinbutton)),
+                           priv->color[COLORSEL_GREEN] * 255);
+  gtk_adjustment_set_value (gtk_spin_button_get_adjustment
+                           (GTK_SPIN_BUTTON (priv->blue_spinbutton)),
+                           priv->color[COLORSEL_BLUE] * 255);
+  gtk_adjustment_set_value (gtk_range_get_adjustment
+                           (GTK_RANGE (priv->opacity_slider)),
+                           priv->color[COLORSEL_OPACITY] * 255);
+
+  g_snprintf (opacity_text, 32, "%.0f", priv->color[COLORSEL_OPACITY] * 255);
+  gtk_entry_set_text (GTK_ENTRY (priv->opacity_entry), opacity_text);
+
+  g_snprintf (entryval, 11, "#%2X%2X%2X",
+             (guint) (255 * priv->color[COLORSEL_RED]),
+             (guint) (255 * priv->color[COLORSEL_GREEN]),
+             (guint) (255 * priv->color[COLORSEL_BLUE]));
+
+  for (ptr = entryval; *ptr; ptr++)
+    if (*ptr == ' ')
+      *ptr = '0';
+  gtk_entry_set_text (GTK_ENTRY (priv->hex_entry), entryval);
+  priv->changing = FALSE;
+}
 
-  cx = (gdouble) (wid) / 2.0;
-  cy = (gdouble) (heig) / 2.0;
+static void
+add_button_pressed (GtkWidget *button, GtkColorSelection *colorsel)
+{
+  gint i, j;
+  ColorSelectionPrivate *priv;
 
-  bg[0] = style->bg[GTK_STATE_NORMAL].red >> 8;
-  bg[1] = style->bg[GTK_STATE_NORMAL].green >> 8;
-  bg[2] = style->bg[GTK_STATE_NORMAL].blue >> 8;
+  priv = colorsel->private;
 
-  for (y = 0; y < heig; y++)
+  for (j = 0; j < CUSTOM_PALETTE_HEIGHT; j++)
     {
-      i = 0;
-      for (x = 0; x < wid; x++)
+      for (i = 0; i < CUSTOM_PALETTE_WIDTH; i++)
        {
-         if (gtk_color_selection_eval_wheel (x, y, cx, cy, &h, &s))
-           {
-             for (n = 0; n < 3; n++)
-               colorsel->wheel_buf[i++] = bg[n];
-           }
-         else
+         /* Either last_palette is set and we're on it, or it's an empty palette */
+         if ((priv->last_palette && priv->last_palette == priv->custom_palette[i][j]) ||
+             ((priv->last_palette == NULL) && (GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (priv->custom_palette[i][j]),
+                                                                                     "color_set")) == 0)))
            {
-             gtk_color_selection_hsv_to_rgb (h, s, 1.0, &c[0], &c[1], &c[2]);
-             for (n = 0; n < 3; n++)
-               colorsel->wheel_buf[i++] = (guchar) (255.0 * c[n]);
+             palette_set_color (priv->custom_palette[i][j], colorsel, priv->color);
+             /* forward the selection */
+             if ((i == CUSTOM_PALETTE_WIDTH - 1) && (j == CUSTOM_PALETTE_HEIGHT - 1))
+               gtk_widget_grab_focus (priv->custom_palette[0][0]);
+             else if (i == CUSTOM_PALETTE_WIDTH - 1)
+               gtk_widget_grab_focus (priv->custom_palette[0][j + 1]);
+             else
+               gtk_widget_grab_focus (priv->custom_palette[i + 1][j]);
+             return;
            }
        }
+    }
+  /* the palette is totally full.  Add to the first one totally arbitrarily */
+  palette_set_color (priv->custom_palette[0][0], colorsel, priv->color);
+  /* forward the selection */
+  gtk_widget_grab_focus (priv->custom_palette[1][0]);
+}
+
+GtkType
+gtk_color_selection_get_type (void)
+{
+  static GtkType color_selection_type = 0;
+
+  if (!color_selection_type)
+    {
+      static const GtkTypeInfo color_selection_info =
+      {
+        "GtkColorSelection",
+        sizeof (GtkColorSelection),
+        sizeof (GtkColorSelectionClass),
+        (GtkClassInitFunc) gtk_color_selection_class_init,
+        (GtkObjectInitFunc) gtk_color_selection_init,
+        /* reserved_1 */ NULL,
+        /* reserved_2 */ NULL,
+        (GtkClassInitFunc) NULL,
+      };
 
-      gtk_preview_draw_row (GTK_PREVIEW (colorsel->wheel_area), colorsel->wheel_buf, 0, y, wid);
+      color_selection_type = gtk_type_unique (gtk_vbox_get_type (), &color_selection_info);
     }
 
-  if (colorsel->wheel_area->window)
-     {
-       GdkPixmap *pm = NULL;
-       GdkGC     *pmgc = NULL;
-       GdkColor   col;
-       gint w, h;
-       
-       pm = gdk_pixmap_new (colorsel->wheel_area->window, wid, heig, 1);
-       pmgc = gdk_gc_new (pm);
-       
-       col.pixel = 0;
-       gdk_gc_set_foreground(pmgc, &col);
-       gdk_draw_rectangle(pm, pmgc, TRUE, 0, 0, wid, heig);
-       col.pixel = 1;
-       
-       gdk_gc_set_foreground(pmgc, &col);
-       gdk_draw_arc (pm, pmgc, TRUE, 0, 0, wid, heig, 0, 360*64);
-
-       w = colorsel->wheel_area->allocation.width;
-       h = colorsel->wheel_area->allocation.height;
-       
-       gdk_draw_arc (pm, pmgc,
-                     FALSE, 1, 1, w - 1, h - 1, 30 * 64, 180 * 64);
-       gdk_draw_arc (pm, pmgc,
-                     FALSE, 0, 0, w, h, 30 * 64, 180 * 64);
-       gdk_draw_arc (pm, pmgc,
-                     FALSE, 1, 1, w - 1, h - 1, 210 * 64, 180 * 64);
-       gdk_draw_arc (pm, pmgc,
-                     FALSE, 0, 0, w, h, 210 * 64, 180 * 64);
-       gdk_window_shape_combine_mask (colorsel->wheel_area->window, pm, 0, 0);
-       gdk_pixmap_unref (pm);
-       gdk_gc_destroy (pmgc);
-     }
+  return color_selection_type;
 }
 
 static void
-gtk_color_selection_draw_sample (GtkColorSelection *colorsel,
-                                 gint               resize)
+gtk_color_selection_class_init (GtkColorSelectionClass *klass)
 {
-  gint x, y, i, wid, heig, f, half, n;
-  guchar c[3 * 2], cc[3 * 4], *cp = c;
-  gdouble o, oldo;
+  GtkObjectClass *object_class;
 
-  wid = colorsel->sample_area->allocation.width;
-  heig = colorsel->sample_area->allocation.height;
-  half = wid >> 1;
+  object_class = (GtkObjectClass*) klass;
 
-  if (resize)
-    {
-      if (colorsel->sample_buf != NULL)
-       g_free (colorsel->sample_buf);
+  parent_class = gtk_type_class (gtk_vbox_get_type ());
 
-      colorsel->sample_buf = g_new(guchar, 3 * wid);
-    }
+  color_selection_signals[COLOR_CHANGED] =
+    gtk_signal_new ("color_changed",
+                    GTK_RUN_FIRST,
+                    object_class->type,
+                    GTK_SIGNAL_OFFSET (GtkColorSelectionClass, color_changed),
+                    gtk_marshal_NONE__NONE,
+                    GTK_TYPE_NONE, 0);
 
-  i = RED;
-  for (n = 0; n < 3; n++)
-    {
-      c[n] = (guchar) (255.0 * colorsel->old_values[i]);
-      c[n + 3] = (guchar) (255.0 * colorsel->values[i++]);
-    }
 
-  if (colorsel->use_opacity)
-    {
-      o = colorsel->values[OPACITY];
-      oldo = colorsel->old_values[OPACITY];
+  gtk_object_class_add_signals (object_class, color_selection_signals, LAST_SIGNAL);
 
-      for (n = 0; n < 3; n++)
-       {
-         cc[n] = (guchar) ((1.0 - oldo) * 192 + (oldo * (gdouble) c[n]));
-         cc[n + 3] = (guchar) ((1.0 - oldo) * 128 + (oldo * (gdouble) c[n]));
-         cc[n + 6] = (guchar) ((1.0 - o) * 192 + (o * (gdouble) c[n + 3]));
-         cc[n + 9] = (guchar) ((1.0 - o) * 128 + (o * (gdouble) c[n + 3]));
-       }
-      cp = cc;
-    }
+  object_class->destroy = gtk_color_selection_destroy;
+}
 
-  for (y = 0; y < heig; y++)
+/* widget functions */
+static void
+gtk_color_selection_init (GtkColorSelection *colorsel)
+{
+  GtkWidget *top_hbox;
+  GtkWidget *top_right_vbox;
+  GtkWidget *table, *label, *hbox, *frame, *vbox;
+  GtkAdjustment *adjust;
+  GdkPixmap *dropper_pixmap;
+  GtkWidget *dropper_image;
+  GtkWidget *button;
+  GdkBitmap *mask = NULL;
+  gint i, j;
+  ColorSelectionPrivate *priv;
+
+  priv = colorsel->private = g_new (ColorSelectionPrivate, 1);
+  priv->changing = FALSE;
+  priv->default_set = FALSE;
+  priv->last_palette = NULL;
+  priv->moving_dropper = FALSE;
+
+  gtk_box_set_spacing (GTK_BOX (colorsel), 4);
+  top_hbox = gtk_hbox_new (FALSE, 8);
+  gtk_box_pack_start (GTK_BOX (colorsel), top_hbox, FALSE, FALSE, 0);
+
+  vbox = gtk_vbox_new (FALSE, 4);
+  priv->triangle_colorsel = gtk_hsv_new ();
+  gtk_signal_connect (GTK_OBJECT (priv->triangle_colorsel), "changed", hsv_changed, colorsel);
+  gtk_hsv_set_metrics (GTK_HSV (priv->triangle_colorsel), 174, 15);
+  gtk_box_pack_start (GTK_BOX (top_hbox), vbox, FALSE, FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox), priv->triangle_colorsel, FALSE, FALSE, 0);
+
+  hbox = gtk_hbox_new (FALSE, 4);
+  gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+  frame = gtk_frame_new (NULL);
+  gtk_widget_set_usize (frame, -1, 30);
+  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+  color_sample_new (colorsel);
+  gtk_container_add (GTK_CONTAINER (frame), priv->sample_area);
+  gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
+
+  button = gtk_button_new ();
+  gtk_signal_connect (GTK_OBJECT (button), "focus_in_event", widget_focus_in, colorsel);
+  gtk_widget_set_events (button, GDK_POINTER_MOTION_MASK
+                                | GDK_POINTER_MOTION_HINT_MASK);
+  gtk_object_set_data (GTK_OBJECT (button), "COLORSEL", colorsel); 
+  gtk_signal_connect (GTK_OBJECT (button), "clicked", get_screen_color, NULL);
+  dropper_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, gtk_widget_get_colormap (button), &mask, NULL, picker);
+  dropper_image = gtk_pixmap_new (dropper_pixmap, mask);
+  gtk_container_add (GTK_CONTAINER (button), dropper_image);
+  label = gtk_label_new (_("Color Picker"));
+  gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+
+  top_right_vbox = gtk_vbox_new (FALSE, 4);
+  gtk_box_pack_start (GTK_BOX (top_hbox), top_right_vbox, FALSE, FALSE, 0);
+  table = gtk_table_new (8, 6, FALSE);
+  gtk_box_pack_start (GTK_BOX (top_right_vbox), table, FALSE, FALSE, 0);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 4);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 4);
+
+  make_label_spinbutton (colorsel, &priv->hue_spinbutton, _("Hue:"), table, 0, 0, COLORSEL_HUE);
+  make_label_spinbutton (colorsel, &priv->sat_spinbutton, _("Saturation:"), table, 0, 1, COLORSEL_SATURATION);
+  make_label_spinbutton (colorsel, &priv->val_spinbutton, _("Value:"), table, 0, 2, COLORSEL_VALUE);
+  make_label_spinbutton (colorsel, &priv->red_spinbutton, _("Red:"), table, 6, 0, COLORSEL_RED);
+  make_label_spinbutton (colorsel, &priv->green_spinbutton, _("Green:"), table, 6, 1, COLORSEL_GREEN);
+  make_label_spinbutton (colorsel, &priv->blue_spinbutton, _("Blue:"), table, 6, 2, COLORSEL_BLUE);
+  gtk_table_attach_defaults (GTK_TABLE (table), gtk_hseparator_new (), 0, 8, 3, 4); 
+
+  priv->opacity_label = gtk_label_new (_("Opacity:")); 
+  gtk_misc_set_alignment (GTK_MISC (priv->opacity_label), 1.0, 0.5); 
+  gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_label, 0, 1, 4, 5); 
+  adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 0.0)); 
+  gtk_object_set_data (GTK_OBJECT (adjust), "COLORSEL", colorsel); 
+  priv->opacity_slider = gtk_hscale_new (adjust); 
+  gtk_scale_set_draw_value (GTK_SCALE (priv->opacity_slider), FALSE);
+  gtk_signal_connect (GTK_OBJECT(adjust), "value_changed", adjustment_changed, GINT_TO_POINTER (COLORSEL_OPACITY));
+  gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_slider, 1, 7, 4, 5); 
+  priv->opacity_entry = gtk_entry_new (); 
+  gtk_widget_set_usize (priv->opacity_entry, 40, 0); 
+  gtk_signal_connect (GTK_OBJECT (priv->opacity_entry), "focus_in_event", widget_focus_in, colorsel);
+  gtk_signal_connect (GTK_OBJECT (priv->opacity_entry), "activate", opacity_entry_changed, colorsel);
+  gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_entry, 7, 8, 4, 5);
+
+  label = gtk_label_new (_("Hex Value:"));
+  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 5, 6);
+  gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
+  priv->hex_entry = gtk_entry_new ();
+  gtk_signal_connect (GTK_OBJECT (priv->hex_entry), "activate", hex_changed, colorsel);
+  gtk_widget_set_usize (priv->hex_entry, 75, -1);  
+  gtk_table_set_col_spacing (GTK_TABLE (table), 3, 25);
+  gtk_table_attach_defaults (GTK_TABLE (table), priv->hex_entry, 1, 5, 5, 6);
+
+  /* Set up the palette */
+  table = gtk_table_new (CUSTOM_PALETTE_HEIGHT, CUSTOM_PALETTE_WIDTH, TRUE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 1);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 1);
+  for (i = 0; i < CUSTOM_PALETTE_WIDTH; i++)
     {
-      i = 0;
-      for (x = 0; x < wid; x++)
+      for (j = 0; j < CUSTOM_PALETTE_HEIGHT; j++)
        {
-         if (colorsel->use_opacity)
-           {
-             f = 3 * (((x % 32) < 16) ^ ((y % 32) < 16));
-             f += (x > half) * 6;
-           }
-         else
-           f = (x > half) * 3;
-
-         for (n = 0; n < 3; n++)
-           colorsel->sample_buf[i++] = cp[n + f];
+         make_palette_frame (colorsel, table, i, j);
        }
+    }
+  priv->palette_frame = gtk_frame_new (_("Custom Palette"));
+  gtk_box_pack_end (GTK_BOX (top_right_vbox), priv->palette_frame, FALSE, FALSE, 0);
+  vbox = gtk_vbox_new (FALSE, 4);
+  gtk_container_add (GTK_CONTAINER (priv->palette_frame), vbox);
+  gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
+  button = gtk_button_new_with_label (_("Set Color"));
+  gtk_signal_connect (GTK_OBJECT (button), "clicked", add_button_pressed, colorsel);
+  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
+
+  gtk_widget_show_all (top_hbox);
+
+  if (priv->use_opacity == FALSE)
+    {
+      gtk_widget_hide (priv->opacity_label);
+      gtk_widget_hide (priv->opacity_slider);
+      gtk_widget_hide (priv->opacity_entry);
+    }
 
-      gtk_preview_draw_row (GTK_PREVIEW (colorsel->sample_area), colorsel->sample_buf, 0, y, wid);
+  if (priv->use_palette == FALSE)
+    {
+      gtk_widget_hide (priv->palette_frame);
     }
+}
 
-  gtk_widget_queue_draw (colorsel->sample_area);
+static void
+gtk_color_selection_destroy (GtkObject *object)
+{
+  g_free (GTK_COLOR_SELECTION (object)->private);
 }
 
-static gint
-gtk_color_selection_eval_wheel (gint     x,  gint     y,
-                               gdouble  cx, gdouble  cy,
-                               gdouble *h,  gdouble *s)
+
+
+/**
+ * gtk_color_selection_new:
+ * @void: 
+ * 
+ * Creates a new GtkColorSelection.
+ * 
+ * Return value: The new GtkColorSelection.
+ **/
+GtkWidget *
+gtk_color_selection_new (void)
 {
-  gdouble r, rx, ry;
+  GtkColorSelection *colorsel;
+  ColorSelectionPrivate *priv;
+  gdouble color[4];
+  color[0] = 1.0;
+  color[1] = 1.0;
+  color[2] = 1.0;
+  color[3] = 1.0;
 
-  rx = ((gdouble) x - cx);
-  ry = ((gdouble) y - cy);
+  colorsel = gtk_type_new (GTK_TYPE_COLOR_SELECTION);
+  priv = colorsel->private;
+  gtk_color_selection_set_color (colorsel, color);
+  gtk_color_selection_set_use_opacity (colorsel, FALSE);
 
-  rx = rx/cx;
-  ry = ry/cy;
+  /* We want to make sure that default_set is FALSE */
+  /* This way the user can still set it */
+  priv->default_set = FALSE;
 
-  r = sqrt (SQR (rx) + SQR (ry));
+  return GTK_WIDGET (colorsel);
+}
 
-  if (r != 0.0)
-    *h = atan2 (rx / r, ry / r);
-  else
-    *h = 0.0;
 
-  *s = r;
-  *h = 360.0 * (*h) / (2.0 * M_PI) + 180;
+void
+gtk_color_selection_set_update_policy (GtkColorSelection    *colorsel,
+                                       GtkUpdateType          policy)
+{
+  g_return_if_fail (colorsel != NULL);
+  g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
+  /* */
+  g_warning ("This function is deprecated.");
+}
+
+/**
+ * gtk_color_selection_get_use_opacity:
+ * @colorsel: A GtkColorSelection.
+ * 
+ * Determines whether the colorsel can use opacity.
+ * 
+ * Return value: TRUE if the @colorsel uses opacity.  FALSE if it does't.
+ **/
+gboolean
+gtk_color_selection_get_use_opacity   (GtkColorSelection    *colorsel)
+{
+  ColorSelectionPrivate *priv;
+  g_return_val_if_fail (colorsel != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
 
-  if (*s == 0.0)
-    *s = 0.00001;
-  else if (*s > 1.0)
-    {
-      *s = 1.0;
-      return TRUE;
-    }
-  return FALSE;
+  priv = colorsel->private;
+  return priv->use_opacity;
 }
 
-static void
-gtk_color_selection_hsv_to_rgb (gdouble  h, gdouble  s, gdouble  v,
-                               gdouble *r, gdouble *g, gdouble *b)
+/**
+ * gtk_color_selection_set_use_opacity:
+ * @colorsel: A GtkColorSelection.
+ * @use_opacity: TRUE if @colorsel can set the opacity, FALSE otherwise.
+ *
+ * Sets the @colorsel to use or not use opacity.
+ * 
+ **/
+void
+gtk_color_selection_set_use_opacity   (GtkColorSelection    *colorsel,
+                                       gboolean               use_opacity)
 {
-  gint i;
-  gdouble f, w, q, t;
+  ColorSelectionPrivate *priv;
+  g_return_if_fail (colorsel != NULL);
+  g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
 
-  if (s == 0.0)
-    s = 0.000001;
+  priv = colorsel->private;
+  if (priv->use_opacity == use_opacity)
+    return;
 
-  if (h == -1.0)
+  priv->use_opacity = use_opacity;
+  if (use_opacity)
     {
-      *r = v;
-      *g = v;
-      *b = v;
+      gtk_widget_show (priv->opacity_slider);
+      gtk_widget_show (priv->opacity_label);
+      gtk_widget_show (priv->opacity_entry);
     }
   else
     {
-      if (h == 360.0)
-       h = 0.0;
-      h = h / 60.0;
-      i = (gint) h;
-      f = h - i;
-      w = v * (1.0 - s);
-      q = v * (1.0 - (s * f));
-      t = v * (1.0 - (s * (1.0 - f)));
-
-      switch (i)
-       {
-       case 0:
-         *r = v;
-         *g = t;
-         *b = w;
-         break;
-       case 1:
-         *r = q;
-         *g = v;
-         *b = w;
-         break;
-       case 2:
-         *r = w;
-         *g = v;
-         *b = t;
-         break;
-       case 3:
-         *r = w;
-         *g = q;
-         *b = v;
-         break;
-       case 4:
-         *r = t;
-         *g = w;
-         *b = v;
-         break;
-       case 5:
-         *r = v;
-         *g = w;
-         *b = q;
-         break;
-       }
+      gtk_widget_hide (priv->opacity_slider);
+      gtk_widget_hide (priv->opacity_label);
+      gtk_widget_hide (priv->opacity_entry);
     }
+  color_sample_set_use_opacity (colorsel);
 }
 
-static void
-gtk_color_selection_rgb_to_hsv (gdouble  r, gdouble  g, gdouble  b,
-                               gdouble *h, gdouble *s, gdouble *v)
+/**
+ * gtk_color_selection_get_use_palette:
+ * @colorsel: A GtkColorSelection.
+ * 
+ * Determines whether the palette is used.
+ * 
+ * Return value: TRUE if the palette is used.  FALSE if it isn't.
+ **/
+gboolean
+gtk_color_selection_get_use_palette   (GtkColorSelection    *colorsel)
 {
-  double max, min, delta;
-
-  max = r;
-  if (g > max)
-    max = g;
-  if (b > max)
-    max = b;
+  ColorSelectionPrivate *priv;
+  g_return_val_if_fail (colorsel != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
 
-  min = r;
-  if (g < min)
-    min = g;
-  if (b < min)
-    min = b;
+  priv = colorsel->private;
+  return priv->use_palette;
+}
 
-  *v = max;
+/**
+ * gtk_color_selection_set_use_palette:
+ * @colorsel: A GtkColorSelection.
+ * @use_palette: TRUE if palette is to be visible, FALSE otherwise.
+ *
+ * Shows and hides the palette based upon the value of @use_palette.
+ * 
+ **/
+void
+gtk_color_selection_set_use_palette   (GtkColorSelection    *colorsel,
+                                       gboolean               use_palette)
+{
+  ColorSelectionPrivate *priv;
+  g_return_if_fail (colorsel != NULL);
+  g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
 
-  if (max != 0.0)
-    *s = (max - min) / max;
-  else
-    *s = 0.0;
+  priv = colorsel->private;
+  if (priv->use_palette == use_palette)
+    return;
 
-  if (*s == 0.0)
-    *h = -1.0;
+  priv->use_palette = use_palette;
+  if (use_palette)
+    gtk_widget_show (priv->palette_frame);
   else
-    {
-      delta = max - min;
+    gtk_widget_hide (priv->palette_frame);
+}
 
-      if (r == max)
-       *h = (g - b) / delta;
-      else if (g == max)
-       *h = 2.0 + (b - r) / delta;
-      else if (b == max)
-       *h = 4.0 + (r - g) / delta;
+/**
+ * gtk_color_selection_set_color:
+ * @colorsel: A GtkColorSelection.
+ * @color: A color to set the current color with.
+ *
+ * Sets the current color to be @color.  The first time this is called, it will
+ * also set the original color to be @color too.
+ * 
+ **/
+void
+gtk_color_selection_set_color         (GtkColorSelection    *colorsel,
+                                       gdouble               *color)
+{
+  ColorSelectionPrivate *priv;
+  gint i;
 
-      *h = *h * 60.0;
+  g_return_if_fail (colorsel != NULL);
+  g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
 
-      if (*h < 0.0)
-       *h = *h + 360;
+  priv = colorsel->private;
+  priv->changing = TRUE;
+  priv->color[COLORSEL_RED] = color[0];
+  priv->color[COLORSEL_GREEN] = color[1];
+  priv->color[COLORSEL_BLUE] = color[2];
+  priv->color[COLORSEL_OPACITY] = color[3];
+  gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
+                 priv->color[COLORSEL_GREEN],
+                 priv->color[COLORSEL_BLUE],
+                 &priv->color[COLORSEL_HUE],
+                 &priv->color[COLORSEL_SATURATION],
+                 &priv->color[COLORSEL_VALUE]);
+  if (priv->default_set == FALSE)
+    {
+      for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
+       priv->old_color[i] = priv->color[i];
     }
+  update_color (colorsel);
+  priv->default_set = TRUE;
 }
 
-/***************************/
-/* GtkColorSelectionDialog */
-/***************************/
+/**
+ * gtk_color_selection_get_color:
+ * @colorsel: A GtkColorSelection.
+ * @color: A color to fill in with the current color.
+ *
+ * Sets @color to be the current color in the GtkColorSelection widget.
+ * 
+ **/
+void
+gtk_color_selection_get_color         (GtkColorSelection    *colorsel,
+                                       gdouble               *color)
+{
+  ColorSelectionPrivate *priv;
+
+  g_return_if_fail (colorsel != NULL);
+  g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
 
-GtkType
-gtk_color_selection_dialog_get_type (void)
+  priv = colorsel->private;
+  color[0] = priv->color[COLORSEL_RED];
+  color[1] = priv->color[COLORSEL_GREEN];
+  color[2] = priv->color[COLORSEL_BLUE];
+  color[3] = priv->use_opacity ? priv->color[COLORSEL_OPACITY] : 1.0;
+}
+
+/**
+ * gtk_color_selection_get_old_color:
+ * @colorsel: A GtkColorSelection.
+ * @color: A color to set the original color with.
+ *
+ * Sets the 'original' color to be @color.  This function should be called with
+ * some hesitations, as it might seem confusing to have that color change.
+ * Calling gtk_color_selection_set_color will also set this color the first
+ * time it is called.
+ * 
+ **/
+void
+gtk_color_selection_set_old_color (GtkColorSelection    *colorsel,
+                                   gdouble               *color)
 {
-  static GtkType color_selection_dialog_type = 0;
+  ColorSelectionPrivate *priv;
 
-  if (!color_selection_dialog_type)
-    {
-      GtkTypeInfo colorsel_diag_info =
-      {
-       "GtkColorSelectionDialog",
-       sizeof (GtkColorSelectionDialog),
-       sizeof (GtkColorSelectionDialogClass),
-       (GtkClassInitFunc) gtk_color_selection_dialog_class_init,
-       (GtkObjectInitFunc) gtk_color_selection_dialog_init,
-       /* reserved_1 */ NULL,
-       /* reserved_2 */ NULL,
-        (GtkClassInitFunc) NULL,
-      };
+  g_return_if_fail (colorsel != NULL);
+  g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
 
-      color_selection_dialog_type = gtk_type_unique (GTK_TYPE_WINDOW, &colorsel_diag_info);
-    }
+  priv = colorsel->private;
+  priv->changing = TRUE;
+  priv->old_color[COLORSEL_RED] = color[0];
+  priv->old_color[COLORSEL_GREEN] = color[1];
+  priv->old_color[COLORSEL_BLUE] = color[2];
+  priv->old_color[COLORSEL_OPACITY] = color[3];
+  gtk_rgb_to_hsv (priv->old_color[COLORSEL_RED],
+                 priv->old_color[COLORSEL_GREEN],
+                 priv->old_color[COLORSEL_BLUE],
+                 &priv->old_color[COLORSEL_HUE],
+                 &priv->old_color[COLORSEL_SATURATION],
+                 &priv->old_color[COLORSEL_VALUE]);
+  color_sample_draw_samples (colorsel);
+  priv->default_set = TRUE;
+}
+
+/**
+ * gtk_color_selection_get_old_color:
+ * @colorsel: A GtkColorSelection.
+ * @color: A color to fill in with the original color value.
+ *
+ * Fills @color in with the original color value.
+ * 
+ **/
+void
+gtk_color_selection_get_old_color (GtkColorSelection    *colorsel,
+                                   gdouble               *color)
+{
+  ColorSelectionPrivate *priv;
 
-  return color_selection_dialog_type;
+  g_return_if_fail (colorsel != NULL);
+  g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
+
+  priv = colorsel->private;
+  color[0] = priv->old_color[COLORSEL_RED];
+  color[1] = priv->old_color[COLORSEL_GREEN];
+  color[2] = priv->old_color[COLORSEL_BLUE];
+  color[3] = priv->use_opacity ? priv->old_color[COLORSEL_OPACITY] : 1.0;
 }
 
-static void
-gtk_color_selection_dialog_class_init (GtkColorSelectionDialogClass *klass)
+/**
+ * gtk_color_selection_set_palette_color:
+ * @colorsel: A GtkColorSelection.
+ * @x: The x coordinate of the palette.
+ * @y: The y coordinate of the palette.
+ * @color: A color to set the palette with.
+ *
+ * Set the palette located at (@x, @y) to have @color set as its color.
+ * 
+ **/
+void
+gtk_color_selection_set_palette_color (GtkColorSelection   *colorsel,
+                                       gint                  x,
+                                       gint                  y,
+                                       gdouble              *color)
 {
-  GtkObjectClass *object_class;
+  ColorSelectionPrivate *priv;
 
-  object_class = (GtkObjectClass*) klass;
+  g_return_if_fail (colorsel != NULL);
+  g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
+  g_return_if_fail (x >= 0 && y >= 0 && x < CUSTOM_PALETTE_WIDTH && y < CUSTOM_PALETTE_HEIGHT);
 
-  color_selection_dialog_parent_class = gtk_type_class (GTK_TYPE_WINDOW);
+  priv = colorsel->private;
+  palette_set_color (priv->custom_palette[x][y], colorsel, color);
 }
 
-static void
-gtk_color_selection_dialog_init (GtkColorSelectionDialog *colorseldiag)
+/**
+ * gtk_color_selection_get_palette_color:
+ * @colorsel: A GtkColorSelection.
+ * @x: The x coordinate of the palette.
+ * @y: The y coordinate of the palette.
+ * @color: A color to fill in with the color value.
+ * 
+ * Set @color to have the color found in the palette located at (@x, @y).  If
+ * the palette is unset, it will leave the color unset.
+ * 
+ * Return value: TRUE if the palette located at (@x, @y) has a color set.  FALSE
+ * if it doesn't.
+ **/
+gboolean
+gtk_color_selection_get_palette_color (GtkColorSelection   *colorsel,
+                                       gint                  x,
+                                       gint                  y,
+                                       gdouble              *color)
 {
-  GtkWidget *action_area, *frame;
+  ColorSelectionPrivate *priv;
 
-  gtk_widget_set_visual (GTK_WIDGET (colorseldiag), gdk_rgb_get_visual ());
-  gtk_widget_set_colormap (GTK_WIDGET (colorseldiag), gdk_rgb_get_cmap ());
+  g_return_val_if_fail (colorsel != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
+  g_return_val_if_fail (x >= 0 && y >= 0 && x < CUSTOM_PALETTE_WIDTH && y < CUSTOM_PALETTE_HEIGHT, FALSE);
 
-  gtk_widget_push_visual (gdk_rgb_get_visual ());
-  gtk_widget_push_colormap (gdk_rgb_get_cmap ());
+  priv = colorsel->private;
 
-  colorseldiag->main_vbox = gtk_vbox_new (FALSE, 10);
-  gtk_container_set_border_width (GTK_CONTAINER (colorseldiag), 10);
-  gtk_container_add (GTK_CONTAINER (colorseldiag), colorseldiag->main_vbox);
-  gtk_widget_show (colorseldiag->main_vbox);
+  if (GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (priv->custom_palette[x][y]), "color_set")) == 0)
+    return FALSE;
 
-  frame = gtk_frame_new (NULL);
-  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
-  gtk_container_add (GTK_CONTAINER (colorseldiag->main_vbox), frame);
-  gtk_widget_show (frame);
-
-  colorseldiag->colorsel = gtk_color_selection_new ();
-  gtk_container_add (GTK_CONTAINER (frame), colorseldiag->colorsel);
-  gtk_widget_show (colorseldiag->colorsel);
-
-  action_area = gtk_hbutton_box_new ();
-  gtk_button_box_set_layout(GTK_BUTTON_BOX(action_area), GTK_BUTTONBOX_END);
-  gtk_button_box_set_spacing(GTK_BUTTON_BOX(action_area), 5);
-  gtk_box_pack_end (GTK_BOX (colorseldiag->main_vbox), action_area, FALSE, FALSE, 0);
-  gtk_widget_show (action_area);
-
-  colorseldiag->ok_button = gtk_button_new_with_label (_("OK"));
-  GTK_WIDGET_SET_FLAGS (colorseldiag->ok_button, GTK_CAN_DEFAULT);
-  gtk_box_pack_start (GTK_BOX (action_area), colorseldiag->ok_button, TRUE, TRUE, 0);
-  gtk_widget_grab_default (colorseldiag->ok_button);
-  gtk_widget_show (colorseldiag->ok_button);
-
-  colorseldiag->cancel_button = gtk_button_new_with_label (_("Cancel"));
-  GTK_WIDGET_SET_FLAGS (colorseldiag->cancel_button, GTK_CAN_DEFAULT);
-  gtk_box_pack_start (GTK_BOX (action_area), colorseldiag->cancel_button, TRUE, TRUE, 0);
-  gtk_widget_show (colorseldiag->cancel_button);
-
-  colorseldiag->help_button = gtk_button_new_with_label (_("Help"));
-  GTK_WIDGET_SET_FLAGS (colorseldiag->help_button, GTK_CAN_DEFAULT);
-  gtk_box_pack_start (GTK_BOX (action_area), colorseldiag->help_button, TRUE, TRUE, 0);
-  gtk_widget_show (colorseldiag->help_button);
-
-  gtk_widget_pop_colormap ();
-  gtk_widget_pop_visual ();
+  palette_get_color (priv->custom_palette[x][y], color);
+  return TRUE;
+}
+
+/**
+ * gtk_color_selection_unset_palette_color:
+ * @colorsel: A GtkColorSelection.
+ * @x: The x coordinate of the palette.
+ * @y: The y coordinate of the palette.
+ *
+ * Change the palette located at (@x, @y) to have no color set.
+ * 
+ **/
+void
+gtk_color_selection_unset_palette_color (GtkColorSelection   *colorsel,
+                                         gint                  x,
+                                         gint                  y)
+{
+  ColorSelectionPrivate *priv;
+
+  g_return_if_fail (colorsel != NULL);
+  g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
+  g_return_if_fail (x >= 0 && y >= 0 && x < CUSTOM_PALETTE_WIDTH && y < CUSTOM_PALETTE_HEIGHT);
+
+  priv = colorsel->private;
+  palette_unset_color (priv->custom_palette[x][y]);
 }
 
-GtkWidget*
-gtk_color_selection_dialog_new (const gchar *title)
+/**
+ * gtk_color_selection_is_adjusting:
+ * @colorsel: A GtkColorSelection.
+ *
+ * Gets the current state of the @colorsel.
+ *
+ * Return value: TRUE if the user is currently dragging a color around, and FALSE
+ * if the selection has stopped.
+ **/
+gboolean
+gtk_color_selection_is_adjusting (GtkColorSelection    *colorsel)
 {
-  GtkColorSelectionDialog *colorseldiag;
+  ColorSelectionPrivate *priv;
 
-  colorseldiag = gtk_type_new (GTK_TYPE_COLOR_SELECTION_DIALOG);
-  gtk_window_set_title (GTK_WINDOW (colorseldiag), title);
+  g_return_val_if_fail (colorsel != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
+  
+  priv = colorsel->private;
 
-  return GTK_WIDGET (colorseldiag);
+  return (gtk_hsv_is_adjusting (GTK_HSV (priv->triangle_colorsel)));
 }
index 14e622e7d164d3f0a2ba17735455d33fd09a7532..56f11bd8065941084b343a7f15a0b7afea03a778 100644 (file)
@@ -1,4 +1,5 @@
 /* GTK - The GIMP Toolkit
+ * Copyright (C) 2000 Red Hat, Inc. 
  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
  *
  * This library is free software; you can redistribute it and/or
  * files for a list of changes.  These files are distributed with
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
+#ifndef __GTK_COLOR_SELECTION_H__
+#define __GTK_COLOR_SELECTION_H__
 
-#ifndef __GTK_COLORSEL_H__
-#define __GTK_COLORSEL_H__
-
-#include <gtk/gtkwindow.h>
+#include <gtk/gtkdialog.h>
 #include <gtk/gtkvbox.h>
-#include <gtk/gtkframe.h>
-#include <gtk/gtkpreview.h>
-#include <gtk/gtkbutton.h>
-#include <gtk/gtkentry.h>
-#include <gtk/gtkhbox.h>
-#include <gtk/gtklabel.h>
-#include <gtk/gtkmain.h>
-#include <gtk/gtksignal.h>
-#include <gtk/gtkmisc.h>
-#include <gtk/gtkrange.h>
-#include <gtk/gtkscale.h>
-#include <gtk/gtkhscale.h>
-#include <gtk/gtktable.h>
-#include <gtk/gtkeventbox.h>
-
 
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
 
-
-#define GTK_TYPE_COLOR_SELECTION            (gtk_color_selection_get_type ())
-#define GTK_COLOR_SELECTION(obj)            (GTK_CHECK_CAST ((obj), GTK_TYPE_COLOR_SELECTION, GtkColorSelection))
-#define GTK_COLOR_SELECTION_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_COLOR_SELECTION, GtkColorSelectionClass))
-#define GTK_IS_COLOR_SELECTION(obj)         (GTK_CHECK_TYPE ((obj), GTK_TYPE_COLOR_SELECTION))
-#define GTK_IS_COLOR_SELECTION_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_COLOR_SELECTION))
-#define GTK_COLOR_SELECTION_GET_CLASS(obj)  (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_COLOR_SELECTION, GtkColorSelectionClass))
+#define GTK_TYPE_COLOR_SELECTION                       (gtk_color_selection_get_type ())
+#define GTK_COLOR_SELECTION(obj)                       (GTK_CHECK_CAST ((obj), GTK_TYPE_COLOR_SELECTION, GtkColorSelection))
+#define GTK_COLOR_SELECTION_CLASS(klass)               (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_COLOR_SELECTION, GtkColorSelectionClass))
+#define GTK_IS_COLOR_SELECTION(obj)                    (GTK_CHECK_TYPE ((obj), GTK_TYPE_COLOR_SELECTION))
+#define GTK_IS_COLOR_SELECTION_CLASS(klass)            (GTK_CHECK_CLASS_TYPE ((obj), GTK_TYPE_COLOR_SELECTION))
+#define GTK_COLOR_SELECTION_GET_CLASS(obj)              (GTK_CHECK_GET_CLAS ((obj), GTK_TYPE_COLOR_SELECTION, GtkColorSelectionClass))
 
 
-#define GTK_TYPE_COLOR_SELECTION_DIALOG            (gtk_color_selection_dialog_get_type ())
-#define GTK_COLOR_SELECTION_DIALOG(obj)            (GTK_CHECK_CAST ((obj), GTK_TYPE_COLOR_SELECTION_DIALOG, GtkColorSelectionDialog))
-#define GTK_COLOR_SELECTION_DIALOG_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_COLOR_SELECTION_DIALOG, GtkColorSelectionDialogClass))
-#define GTK_IS_COLOR_SELECTION_DIALOG(obj)         (GTK_CHECK_TYPE ((obj), GTK_TYPE_COLOR_SELECTION_DIALOG))
-#define GTK_IS_COLOR_SELECTION_DIALOG_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_COLOR_SELECTION_DIALOG))
-#define GTK_COLOR_SELECTION_DIALOG_GET_CLASS(obj)  (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_COLOR_SELECTION_DIALOG, GtkColorSelectionDialogClass))
+/* Number of elements in the custom palatte */
+#define CUSTOM_PALETTE_WIDTH 10
+#define CUSTOM_PALETTE_HEIGHT 2
 
-typedef struct _GtkColorSelection             GtkColorSelection;
-typedef struct _GtkColorSelectionClass        GtkColorSelectionClass;
-
-typedef struct _GtkColorSelectionDialog       GtkColorSelectionDialog;
-typedef struct _GtkColorSelectionDialogClass  GtkColorSelectionDialogClass;
+typedef struct _GtkColorSelection       GtkColorSelection;
+typedef struct _GtkColorSelectionClass  GtkColorSelectionClass;
 
 
 struct _GtkColorSelection
 {
-  GtkVBox vbox;
-
-  GtkWidget *wheel_area;
-  GtkWidget *value_area;
-  GtkWidget *sample_area;
-  GtkWidget *sample_area_eb;
-
-  GtkWidget *scales[8];
-  GtkWidget *entries[8];
-  GtkWidget *opacity_label;
-
-  GdkGC *wheel_gc;
-  GdkGC *value_gc;
-  GdkGC *sample_gc;
-
-  GtkUpdateType policy;
-  gint use_opacity;
-  gint timer_active;
-  gint timer_tag;
-  gdouble values[8];
-  gdouble old_values[8];
-
-  guchar *wheel_buf;
-  guchar *value_buf;
-  guchar *sample_buf;
+  GtkVBox parent;
+
+  /* < private > */
+  gpointer private;
 };
 
 struct _GtkColorSelectionClass
 {
   GtkVBoxClass parent_class;
 
-  void (* color_changed) (GtkColorSelection *colorsel);
-};
-
-struct _GtkColorSelectionDialog
-{
-  GtkWindow window;
-
-  GtkWidget *colorsel;
-  GtkWidget *main_vbox;
-  GtkWidget *ok_button;
-  GtkWidget *reset_button;
-  GtkWidget *cancel_button;
-  GtkWidget *help_button;
-};
-
-struct _GtkColorSelectionDialogClass
-{
-  GtkWindowClass parent_class;
+  void (*color_changed)        (GtkColorSelection *color_selection);
 };
 
 
-/* ColorSelection */
+/* ColorSelection */ 
 
 GtkType    gtk_color_selection_get_type          (void);
-
-GtkWidget* gtk_color_selection_new               (void);
-
-void       gtk_color_selection_set_update_policy (GtkColorSelection     *colorsel,
-                                                  GtkUpdateType          policy);
-
-void       gtk_color_selection_set_opacity       (GtkColorSelection     *colorsel,
-                                                  gint                   use_opacity);
-
-void       gtk_color_selection_set_color         (GtkColorSelection     *colorsel,
-                                                 gdouble               *color);
-
-void       gtk_color_selection_get_color         (GtkColorSelection     *colorsel,
-                                                  gdouble               *color);
-
-/* ColorSelectionDialog */
-
-GtkType    gtk_color_selection_dialog_get_type   (void);
-
-GtkWidget* gtk_color_selection_dialog_new        (const gchar *title);
+GtkWidget *gtk_color_selection_new               (void);
+void       gtk_color_selection_set_update_policy (GtkColorSelection *colorsel,
+                                                 GtkUpdateType      policy);
+gboolean   gtk_color_selection_get_use_opacity   (GtkColorSelection *colorsel);
+void       gtk_color_selection_set_use_opacity   (GtkColorSelection *colorsel,
+                                                 gboolean           use_opacity);
+gboolean   gtk_color_selection_get_use_palette   (GtkColorSelection *colorsel);
+void       gtk_color_selection_set_use_palette   (GtkColorSelection *colorsel,
+                                                 gboolean           use_palette);
+
+/* The Color set is an array of doubles, of the following format:
+ * color[0] = red_channel;
+ * color[1] = green_channel;
+ * color[2] = blue_channel;
+ * color[3] = alpha_channel;
+ */
+void       gtk_color_selection_set_color          (GtkColorSelection    *colorsel,
+                                                   gdouble               *color);
+void       gtk_color_selection_get_color          (GtkColorSelection    *colorsel,
+                                                   gdouble               *color);
+void       gtk_color_selection_set_old_color      (GtkColorSelection    *colorsel,
+                                                   gdouble               *color);
+void       gtk_color_selection_get_old_color      (GtkColorSelection    *colorsel,
+                                                   gdouble               *color);
+void       gtk_color_selection_set_palette_color  (GtkColorSelection   *colorsel,
+                                                   gint                  x,
+                                                   gint                  y,
+                                                   gdouble              *color);
+gboolean   gtk_color_selection_get_palette_color  (GtkColorSelection   *colorsel,
+                                                   gint                  x,
+                                                   gint                  y,
+                                                   gdouble              *color);
+void       gtk_color_selection_unset_palette_color(GtkColorSelection   *colorsel,
+                                                   gint                  x,
+                                                   gint                  y);
+gboolean   gtk_color_selection_is_adjusting       (GtkColorSelection    *colorsel);
 
 
 #ifdef __cplusplus
@@ -156,4 +112,4 @@ GtkWidget* gtk_color_selection_dialog_new        (const gchar *title);
 #endif /* __cplusplus */
 
 
-#endif /* __GTK_COLORSEL_H__ */
+#endif /* __GTK_COLOR_SELECTION_H__ */
diff --git a/gtk/gtkcolorseldialog.c b/gtk/gtkcolorseldialog.c
new file mode 100644 (file)
index 0000000..c884ca9
--- /dev/null
@@ -0,0 +1,138 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+#include <glib.h>
+#include "gtkcolorseldialog.h"
+#include "gtkframe.h"
+#include "gtkhbbox.h"
+#include "gtkbutton.h"
+
+
+static void gtk_color_selection_dialog_class_init (GtkColorSelectionDialogClass *klass);
+static void gtk_color_selection_dialog_init (GtkColorSelectionDialog *colorseldiag);
+
+static GtkWindowClass *color_selection_dialog_parent_class = NULL;
+
+
+/***************************/
+/* GtkColorSelectionDialog */
+/***************************/
+
+GtkType
+gtk_color_selection_dialog_get_type (void)
+{
+  static GtkType color_selection_dialog_type = 0;
+
+  if (!color_selection_dialog_type)
+    {
+      GtkTypeInfo colorsel_diag_info =
+      {
+       "GtkColorSelectionDialog",
+       sizeof (GtkColorSelectionDialog),
+       sizeof (GtkColorSelectionDialogClass),
+       (GtkClassInitFunc) gtk_color_selection_dialog_class_init,
+       (GtkObjectInitFunc) gtk_color_selection_dialog_init,
+       /* reserved_1 */ NULL,
+       /* reserved_2 */ NULL,
+        (GtkClassInitFunc) NULL,
+      };
+
+      color_selection_dialog_type = gtk_type_unique (GTK_TYPE_DIALOG, &colorsel_diag_info);
+    }
+
+  return color_selection_dialog_type;
+}
+
+static void
+gtk_color_selection_dialog_class_init (GtkColorSelectionDialogClass *klass)
+{
+  GtkObjectClass *object_class;
+
+  object_class = (GtkObjectClass*) klass;
+
+  color_selection_dialog_parent_class = gtk_type_class (GTK_TYPE_DIALOG);
+}
+
+static void
+gtk_color_selection_dialog_init (GtkColorSelectionDialog *colorseldiag)
+{
+  GtkWidget *action_area_button_box, *frame;
+
+  gtk_widget_set_visual (GTK_WIDGET (colorseldiag), gdk_rgb_get_visual ());
+  gtk_widget_set_colormap (GTK_WIDGET (colorseldiag), gdk_rgb_get_cmap ());
+
+  gtk_widget_push_visual (gdk_rgb_get_visual ());
+  gtk_widget_push_colormap (gdk_rgb_get_cmap ());
+
+  frame = gtk_frame_new (NULL);
+  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (colorseldiag)->vbox), frame);
+  gtk_container_set_border_width (GTK_CONTAINER (frame), 10); 
+  gtk_widget_show (frame); 
+
+  colorseldiag->colorsel = gtk_color_selection_new ();
+  gtk_color_selection_set_use_palette (GTK_COLOR_SELECTION(colorseldiag->colorsel), FALSE); 
+  gtk_color_selection_set_use_opacity (GTK_COLOR_SELECTION(colorseldiag->colorsel), FALSE);
+  gtk_container_add (GTK_CONTAINER (frame), colorseldiag->colorsel);
+  gtk_widget_show (colorseldiag->colorsel);
+
+  action_area_button_box = gtk_hbutton_box_new ();
+  gtk_button_box_set_layout (GTK_BUTTON_BOX(action_area_button_box), GTK_BUTTONBOX_END);
+  gtk_button_box_set_spacing (GTK_BUTTON_BOX(action_area_button_box), 5);
+  gtk_box_pack_end (GTK_BOX (GTK_DIALOG (colorseldiag)->action_area), action_area_button_box, TRUE, TRUE, 0);
+  gtk_widget_show (action_area_button_box);
+
+  colorseldiag->ok_button = gtk_button_new_with_label (_("OK"));
+  GTK_WIDGET_SET_FLAGS (colorseldiag->ok_button, GTK_CAN_DEFAULT);
+  gtk_box_pack_start (GTK_BOX (action_area_button_box), colorseldiag->ok_button, TRUE, TRUE, 0);
+  gtk_widget_grab_default (colorseldiag->ok_button);
+  gtk_widget_show (colorseldiag->ok_button);
+
+  colorseldiag->cancel_button = gtk_button_new_with_label (_("Cancel"));
+  GTK_WIDGET_SET_FLAGS (colorseldiag->cancel_button, GTK_CAN_DEFAULT);
+  gtk_box_pack_start (GTK_BOX (action_area_button_box), colorseldiag->cancel_button, TRUE, TRUE, 0);
+  gtk_widget_show (colorseldiag->cancel_button);
+
+  colorseldiag->help_button = gtk_button_new_with_label (_("Help"));
+  GTK_WIDGET_SET_FLAGS (colorseldiag->help_button, GTK_CAN_DEFAULT);
+  gtk_box_pack_start (GTK_BOX (action_area_button_box), colorseldiag->help_button, TRUE, TRUE, 0);
+  gtk_widget_show (colorseldiag->help_button);
+
+  gtk_widget_pop_colormap ();
+  gtk_widget_pop_visual ();
+}
+
+GtkWidget*
+gtk_color_selection_dialog_new (const gchar *title)
+{
+  GtkColorSelectionDialog *colorseldiag;
+
+  colorseldiag = gtk_type_new (GTK_TYPE_COLOR_SELECTION_DIALOG);
+  gtk_window_set_title (GTK_WINDOW (colorseldiag), title);
+  gtk_window_set_policy(GTK_WINDOW (colorseldiag), FALSE, FALSE, TRUE);
+
+  return GTK_WIDGET (colorseldiag);
+}
+
diff --git a/gtk/gtkcolorseldialog.h b/gtk/gtkcolorseldialog.h
new file mode 100644 (file)
index 0000000..ba6530c
--- /dev/null
@@ -0,0 +1,76 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+#ifndef __GTK_COLOR_SELECTION_DIALOG_H__
+#define __GTK_COLOR_SELECTION_DIALOG_H__
+
+#include <gtk/gtkdialog.h>
+#include <gtk/gtkcolorsel.h>
+#include <gtk/gtkvbox.h>
+#include "gtkintl.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define GTK_TYPE_COLOR_SELECTION_DIALOG            (gtk_color_selection_dialog_get_type ())
+#define GTK_COLOR_SELECTION_DIALOG(obj)            (GTK_CHECK_CAST ((obj), GTK_TYPE_COLOR_SELECTION_DIALOG, GtkColorSelectionDialog))
+#define GTK_COLOR_SELECTION_DIALOG_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_COLOR_SELECTION_DIALOG, GtkColorSelectionDialogClass))
+#define GTK_IS_COLOR_SELECTION_DIALOG(obj)         (GTK_CHECK_TYPE ((obj), GTK_TYPE_COLOR_SELECTION_DIALOG))
+#define GTK_IS_COLOR_SELECTION_DIALOG_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_COLOR_SELECTION_DIALOG))
+#define GTK_COLOR_SELECTION_DIALOG_GET_CLASS(obj)  (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_COLOR_SELECTION_DIALOG, GtkColorSelectionDialogClass))
+
+
+typedef struct _GtkColorSelectionDialog       GtkColorSelectionDialog;
+typedef struct _GtkColorSelectionDialogClass  GtkColorSelectionDialogClass;
+
+
+struct _GtkColorSelectionDialog
+{
+  GtkDialog dialog;
+
+  GtkWidget *colorsel;
+  GtkWidget *ok_button;
+  GtkWidget *cancel_button;
+  GtkWidget *help_button;
+};
+
+struct _GtkColorSelectionDialogClass
+{
+  GtkDialogClass parent_class;
+};
+
+
+/* ColorSelectionDialog */ 
+GtkType    gtk_color_selection_dialog_get_type    (void); 
+GtkWidget* gtk_color_selection_dialog_new         (const gchar *title); 
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_COLOR_SELECTION_DIALOG_H__ */
diff --git a/gtk/gtkhsv.c b/gtk/gtkhsv.c
new file mode 100644 (file)
index 0000000..568a140
--- /dev/null
@@ -0,0 +1,1407 @@
+/* HSV color selector for GTK+
+ *
+ * Copyright (C) 1999 The Free Software Foundation
+ *
+ * Authors: Simon Budig <Simon.Budig@unix-ag.org> (original code)
+ *          Federico Mena-Quintero <federico@gimp.org> (cleanup for GTK+)
+ *          Jonathan Blandford <jrb@redhat.com> (cleanup for GTK+)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <math.h>
+#include "gtksignal.h"
+#include "gtkhsv.h"
+
+\f
+
+/* Default width/height */
+#define DEFAULT_SIZE 100
+
+/* Default ring width */
+#define DEFAULT_RING_WIDTH 10
+
+\f
+
+/* Dragging modes */
+typedef enum {
+       DRAG_NONE,
+       DRAG_H,
+       DRAG_SV
+} DragMode;
+
+/* Private part of the GtkHSV structure */
+typedef struct {
+       /* Color value */
+       double h;
+       double s;
+       double v;
+
+       /* Size and ring width */
+       int size;
+       int ring_width;
+
+       /* Window for capturing events */
+       GdkWindow *window;
+
+       /* GC for drawing */
+       GdkGC *gc;
+
+       /* Dragging mode */
+       DragMode mode;
+} HSVPrivate;
+
+\f
+
+/* Signal IDs */
+
+enum {
+       CHANGED,
+       LAST_SIGNAL
+};
+
+static void gtk_hsv_class_init (GtkHSVClass *class);
+static void gtk_hsv_init (GtkHSV *hsv);
+static void gtk_hsv_destroy (GtkObject *object);
+
+static void gtk_hsv_map (GtkWidget *widget);
+static void gtk_hsv_unmap (GtkWidget *widget);
+static void gtk_hsv_realize (GtkWidget *widget);
+static void gtk_hsv_unrealize (GtkWidget *widget);
+static void gtk_hsv_size_request (GtkWidget *widget, GtkRequisition *requisition);
+static void gtk_hsv_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
+static gint gtk_hsv_button_press (GtkWidget *widget, GdkEventButton *event);
+static gint gtk_hsv_button_release (GtkWidget *widget, GdkEventButton *event);
+static gint gtk_hsv_motion (GtkWidget *widget, GdkEventMotion *event);
+static gint gtk_hsv_expose (GtkWidget *widget, GdkEventExpose *event);
+
+static guint hsv_signals[LAST_SIGNAL];
+
+static GtkWidgetClass *parent_class;
+
+\f
+
+/**
+ * gtk_hsv_get_type:
+ * @void:
+ *
+ * Registers the &GtkHSV class if necessary, and returns the type ID associated
+ * to it.
+ *
+ * Return value: The type ID of the &GtkHSV class.
+ **/
+GtkType
+gtk_hsv_get_type (void)
+{
+       static GtkType hsv_type = 0;
+
+       if (!hsv_type) {
+               static const GtkTypeInfo hsv_info = {
+                       "GtkHSV",
+                       sizeof (GtkHSV),
+                       sizeof (GtkHSVClass),
+                       (GtkClassInitFunc) gtk_hsv_class_init,
+                       (GtkObjectInitFunc) gtk_hsv_init,
+                       NULL, /* reserved_1 */
+                       NULL, /* reserved_2 */
+                       (GtkClassInitFunc) NULL
+               };
+
+               hsv_type = gtk_type_unique (gtk_widget_get_type (), &hsv_info);
+       }
+
+       return hsv_type;
+}
+
+/* Class initialization function for the HSV color selector */
+static void
+gtk_hsv_class_init (GtkHSVClass *class)
+{
+       GtkObjectClass *object_class;
+       GtkWidgetClass *widget_class;
+
+       object_class = (GtkObjectClass *) class;
+       widget_class = (GtkWidgetClass *) class;
+
+       parent_class = gtk_type_class (gtk_widget_get_type ());
+
+       hsv_signals[CHANGED] =
+               gtk_signal_new ("changed",
+                               GTK_RUN_FIRST,
+                               object_class->type,
+                               GTK_SIGNAL_OFFSET (GtkHSVClass, changed),
+                               gtk_marshal_NONE__NONE,
+                               GTK_TYPE_NONE, 0);
+
+       gtk_object_class_add_signals (object_class, hsv_signals, LAST_SIGNAL);
+
+       object_class->destroy = gtk_hsv_destroy;
+
+       widget_class->map = gtk_hsv_map;
+       widget_class->unmap = gtk_hsv_unmap;
+       widget_class->realize = gtk_hsv_realize;
+       widget_class->unrealize = gtk_hsv_unrealize;
+       widget_class->size_request = gtk_hsv_size_request;
+       widget_class->size_allocate = gtk_hsv_size_allocate;
+       widget_class->button_press_event = gtk_hsv_button_press;
+       widget_class->button_release_event = gtk_hsv_button_release;
+       widget_class->motion_notify_event = gtk_hsv_motion;
+       widget_class->expose_event = gtk_hsv_expose;
+}
+
+/* Object initialization function for the HSV color selector */
+static void
+gtk_hsv_init (GtkHSV *hsv)
+{
+       HSVPrivate *priv;
+
+       priv = g_new0 (HSVPrivate, 1);
+       hsv->priv = priv;
+
+       GTK_WIDGET_SET_FLAGS (hsv, GTK_NO_WINDOW);
+
+       priv->h = 0.0;
+       priv->s = 0.0;
+       priv->v = 0.0;
+
+       priv->size = DEFAULT_SIZE;
+       priv->ring_width = DEFAULT_RING_WIDTH;
+}
+
+/* Destroy handler for the HSV color selector */
+static void
+gtk_hsv_destroy (GtkObject *object)
+{
+       GtkHSV *hsv;
+       HSVPrivate *priv;
+
+       g_return_if_fail (object != NULL);
+       g_return_if_fail (GTK_IS_HSV (object));
+
+       hsv = GTK_HSV (object);
+       priv = hsv->priv;
+
+       g_free (priv);
+
+       if (GTK_OBJECT_CLASS (parent_class)->destroy)
+               (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+\f
+
+/* Default signal handlers */
+
+/* Map handler for the HSV color selector */
+static void
+gtk_hsv_map (GtkWidget *widget)
+{
+       GtkHSV *hsv;
+       HSVPrivate *priv;
+
+       hsv = GTK_HSV (widget);
+       priv = hsv->priv;
+
+       if (GTK_WIDGET_MAPPED (widget))
+               return;
+
+       GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+
+       gdk_window_show (priv->window);
+}
+
+/* Unmap handler for the HSV color selector */
+static void
+gtk_hsv_unmap (GtkWidget *widget)
+{
+       GtkHSV *hsv;
+       HSVPrivate *priv;
+
+       hsv = GTK_HSV (widget);
+       priv = hsv->priv;
+
+       if (!GTK_WIDGET_MAPPED (widget))
+               return;
+
+       GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+
+       gdk_window_hide (priv->window);
+}
+
+/* Realize handler for the HSV color selector */
+static void
+gtk_hsv_realize (GtkWidget *widget)
+{
+       GtkHSV *hsv;
+       HSVPrivate *priv;
+       GdkWindowAttr attr;
+       int attr_mask;
+       GdkWindow *parent_window;
+
+       hsv = GTK_HSV (widget);
+       priv = hsv->priv;
+
+       GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+       /* Create window */
+
+       attr.window_type = GDK_WINDOW_CHILD;
+       attr.x = widget->allocation.x;
+       attr.y = widget->allocation.y;
+       attr.width = widget->allocation.width;
+       attr.height = widget->allocation.height;
+       attr.wclass = GDK_INPUT_ONLY;
+       attr.event_mask = gtk_widget_get_events (widget);
+       attr.event_mask |= (GDK_BUTTON_PRESS_MASK
+                           | GDK_BUTTON_RELEASE_MASK
+                           | GDK_POINTER_MOTION_MASK);
+
+       attr_mask = GDK_WA_X | GDK_WA_Y;
+
+       parent_window = gtk_widget_get_parent_window (widget);
+
+       widget->window = parent_window;
+       gdk_window_ref (widget->window);
+
+       priv->window = gdk_window_new (parent_window, &attr, attr_mask);
+       gdk_window_set_user_data (priv->window, hsv);
+
+       widget->style = gtk_style_attach (widget->style, widget->window);
+
+       /* Create GC */
+
+       priv->gc = gdk_gc_new (parent_window);
+}
+
+/* Unrealize handler for the HSV color selector */
+static void
+gtk_hsv_unrealize (GtkWidget *widget)
+{
+       GtkHSV *hsv;
+       HSVPrivate *priv;
+
+       hsv = GTK_HSV (widget);
+       priv = hsv->priv;
+
+       gdk_window_set_user_data (priv->window, NULL);
+       gdk_window_destroy (priv->window);
+       priv->window = NULL;
+
+       gdk_gc_unref (priv->gc);
+       priv->gc = NULL;
+
+       if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+               (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+/* Size_request handler for the HSV color selector */
+static void
+gtk_hsv_size_request (GtkWidget *widget, GtkRequisition *requisition)
+{
+       GtkHSV *hsv;
+       HSVPrivate *priv;
+
+       hsv = GTK_HSV (widget);
+       priv = hsv->priv;
+
+       requisition->width = priv->size;
+       requisition->height = priv->size;
+}
+
+/* Size_allocate handler for the HSV color selector */
+static void
+gtk_hsv_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
+{
+       GtkHSV *hsv;
+       HSVPrivate *priv;
+
+       hsv = GTK_HSV (widget);
+       priv = hsv->priv;
+
+       widget->allocation = *allocation;
+
+       if (GTK_WIDGET_REALIZED (widget))
+               gdk_window_move_resize (priv->window,
+                                       allocation->x,
+                                       allocation->y,
+                                       allocation->width,
+                                       allocation->height);
+}
+
+\f
+
+/* Utility functions */
+
+#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
+
+/* Converts from HSV to RGB */
+static void
+hsv_to_rgb (double *h, double *s, double *v)
+{
+       double hue, saturation, value;
+       double f, p, q, t;
+
+       if (*s == 0.0) {
+               *h = *v;
+               *s = *v;
+               *v = *v; /* heh */
+       } else {
+               hue = *h * 6.0;
+               saturation = *s;
+               value = *v;
+
+               if (hue == 6.0)
+                       hue = 0.0;
+
+               f = hue - (int) hue;
+               p = value * (1.0 - saturation);
+               q = value * (1.0 - saturation * f);
+               t = value * (1.0 - saturation * (1.0 - f));
+
+               switch ((int) hue) {
+               case 0:
+                       *h = value;
+                       *s = t;
+                       *v = p;
+                       break;
+
+               case 1:
+                       *h = q;
+                       *s = value;
+                       *v = p;
+                       break;
+
+               case 2:
+                       *h = p;
+                       *s = value;
+                       *v = t;
+                       break;
+
+               case 3:
+                       *h = p;
+                       *s = q;
+                       *v = value;
+                       break;
+
+               case 4:
+                       *h = t;
+                       *s = p;
+                       *v = value;
+                       break;
+
+               case 5:
+                       *h = value;
+                       *s = p;
+                       *v = q;
+                       break;
+
+               default:
+                       g_assert_not_reached ();
+               }
+       }
+}
+
+/* Converts from RGB to HSV */
+static void
+rgb_to_hsv (double *r, double *g, double *b)
+{
+       double red, green, blue;
+       double h, s, v;
+       double min, max;
+       double delta;
+
+       red = *r;
+       green = *g;
+       blue = *b;
+
+       h = 0.0;
+
+       if (red > green) {
+               if (red > blue)
+                       max = red;
+               else
+                       max = blue;
+
+               if (green < blue)
+                       min = green;
+               else
+                       min = blue;
+       } else {
+               if (green > blue)
+                       max = green;
+               else
+                       max = blue;
+
+               if (red < blue)
+                       min = red;
+               else
+                       min = blue;
+       }
+
+       v = max;
+
+       if (max != 0.0)
+               s = (max - min) / max;
+       else
+               s = 0.0;
+
+       if (s == 0.0)
+               h = 0.0;
+       else {
+               delta = max - min;
+
+               if (red == max)
+                       h = (green - blue) / delta;
+               else if (green == max)
+                       h = 2 + (blue - red) / delta;
+               else if (blue == max)
+                       h = 4 + (red - green) / delta;
+
+               h /= 6.0;
+
+               if (h < 0.0)
+                       h += 1.0;
+               else if (h > 1.0)
+                       h -= 1.0;
+       }
+
+       *r = h;
+       *g = s;
+       *b = v;
+}
+
+/* Computes the vertices of the saturation/value triangle */
+static void
+compute_triangle (GtkHSV *hsv, int *hx, int *hy, int *sx, int *sy, int *vx, int *vy)
+{
+       HSVPrivate *priv;
+       double center;
+       double inner, outer;
+       double angle;
+
+       priv = hsv->priv;
+
+       center = priv->size / 2.0;
+       outer = priv->size / 2.0;
+       inner = outer - priv->ring_width;
+       angle = priv->h * 2.0 * M_PI;
+
+       *hx = floor (center + cos (angle) * inner + 0.5);
+       *hy = floor (center - sin (angle) * inner + 0.5);
+       *sx = floor (center + cos (angle + 2.0 * M_PI / 3.0) * inner + 0.5);
+       *sy = floor (center - sin (angle + 2.0 * M_PI / 3.0) * inner + 0.5);
+       *vx = floor (center + cos (angle + 4.0 * M_PI / 3.0) * inner + 0.5);
+       *vy = floor (center - sin (angle + 4.0 * M_PI / 3.0) * inner + 0.5);
+}
+
+/* Computes whether a point is inside the hue ring */
+static gboolean
+is_in_ring (GtkHSV *hsv, double x, double y)
+{
+       HSVPrivate *priv;
+       double dx, dy, dist;
+       double center, inner, outer;
+
+       priv = hsv->priv;
+
+       center = priv->size / 2.0;
+       outer = priv->size / 2.0;
+       inner = outer - priv->ring_width;
+
+       dx = x - center;
+       dy = center - y;
+       dist = dx * dx + dy * dy;
+
+       return (dist >= inner * inner && dist <= outer * outer);
+}
+
+/* Computes a saturation/value pair based on the mouse coordinates */
+static void
+compute_sv (GtkHSV *hsv, double x, double y, double *s, double *v)
+{
+       HSVPrivate *priv;
+       int ihx, ihy, isx, isy, ivx, ivy;
+       double hx, hy, sx, sy, vx, vy;
+       double center;
+
+       priv = hsv->priv;
+
+       compute_triangle (hsv, &ihx, &ihy, &isx, &isy, &ivx, &ivy);
+       center = priv->size / 2.0;
+       hx = ihx - center;
+       hy = center - ihy;
+       sx = isx - center;
+       sy = center - isy;
+       vx = ivx - center;
+       vy = center - ivy;
+       x -= center;
+       y = center - y;
+
+       if (vx * (x - sx) + vy * (y - sy) < 0.0) {
+               *s = 1.0;
+               *v = (((x - sx) * (hx - sx) + (y - sy) * (hy-sy))
+                     / ((hx - sx) * (hx - sx) + (hy - sy) * (hy - sy)));
+
+               if (*v < 0.0)
+                       *v = 0.0;
+               else if (*v > 1.0)
+                       *v = 1.0;
+       } else if (hx * (x - sx) + hy * (y - sy) < 0.0) {
+               *s = 0.0;
+               *v = (((x - sx) * (vx - sx) + (y - sy) * (vy - sy))
+                     / ((vx - sx) * (vx - sx) + (vy - sy) * (vy - sy)));
+
+               if (*v < 0.0)
+                       *v = 0.0;
+               else if (*v > 1.0)
+                       *v = 1.0;
+       } else if (sx * (x - hx) + sy * (y - hy) < 0.0) {
+               *v = 1.0;
+               *s = (((x - vx) * (hx - vx) + (y - vy) * (hy - vy)) /
+                     ((hx - vx) * (hx - vx) + (hy - vy) * (hy - vy)));
+
+               if (*s < 0.0)
+                       *s = 0.0;
+               else if (*s > 1.0)
+                       *s = 1.0;
+       } else {
+               *v = (((x - sx) * (hy - vy) - (y - sy) * (hx - vx))
+                     / ((vx - sx) * (hy - vy) - (vy - sy) * (hx - vx)));
+
+               if (*v<= 0.0) {
+                       *v = 0.0;
+                       *s = 0.0;
+               } else {
+                       if (*v > 1.0)
+                               *v = 1.0;
+
+                       *s = (y - sy - *v * (vy - sy)) / (*v * (hy - vy));
+                       if (*s < 0.0)
+                               *s = 0.0;
+                       else if (*s > 1.0)
+                               *s = 1.0;
+               }
+       }
+}
+
+/* Computes whether a point is inside the saturation/value triangle */
+static gboolean
+is_in_triangle (GtkHSV *hsv, double x, double y)
+{
+       int hx, hy, sx, sy, vx, vy;
+       double det, s, v;
+
+       compute_triangle (hsv, &hx, &hy, &sx, &sy, &vx, &vy);
+
+       det = (vx - sx) * (hy - sy) - (vy - sy) * (hx - sx);
+
+       s = ((x - sx) * (hy - sy) - (y - sy) * (hx - sx)) / det;
+       v = ((vx - sx) * (y - sy) - (vy - sy) * (x - sx)) / det;
+
+       return (s >= 0.0 && v >= 0.0 && s + v <= 1.0);
+}
+
+/* Computes a value based on the mouse coordinates */
+static double
+compute_v (GtkHSV *hsv, double x, double y)
+{
+       HSVPrivate *priv;
+       double center;
+       double dx, dy;
+       double angle;
+
+       priv = hsv->priv;
+
+       center = priv->size / 2.0;
+       dx = x - center;
+       dy = center - y;
+
+       angle = atan2 (dy, dx);
+       if (angle < 0.0)
+               angle += 2.0 * M_PI;
+
+       return angle / (2.0 * M_PI);
+}
+
+\f
+
+/* Event handlers */
+
+static void
+set_cross_grab (GtkHSV *hsv, guint32 time)
+{
+       HSVPrivate *priv;
+       GdkCursor *cursor;
+
+       priv = hsv->priv;
+
+       cursor = gdk_cursor_new (GDK_CROSSHAIR);
+       gdk_pointer_grab (priv->window, FALSE,
+                         (GDK_POINTER_MOTION_MASK
+                          | GDK_POINTER_MOTION_HINT_MASK
+                          | GDK_BUTTON_RELEASE_MASK),
+                         NULL,
+                         cursor,
+                         time);
+       gdk_cursor_destroy (cursor);
+
+}
+
+/* Button_press_event handler for the HSV color selector */
+static gint
+gtk_hsv_button_press (GtkWidget *widget, GdkEventButton *event)
+{
+       GtkHSV *hsv;
+       HSVPrivate *priv;
+       double x, y;
+
+       hsv = GTK_HSV (widget);
+       priv = hsv->priv;
+
+       if (priv->mode != DRAG_NONE || event->button != 1)
+               return FALSE;
+
+       x = event->x;
+       y = event->y;
+
+       if (is_in_ring (hsv, x, y)) {
+               priv->mode = DRAG_H;
+               set_cross_grab (hsv, event->time);
+
+               gtk_hsv_set_color (hsv,
+                                  compute_v (hsv, x, y),
+                                  priv->s,
+                                  priv->v);
+
+               return TRUE;
+       }
+
+       if (is_in_triangle (hsv, x, y)) {
+               double s, v;
+
+               priv->mode = DRAG_SV;
+               set_cross_grab (hsv, event->time);
+
+               compute_sv (hsv, x, y, &s, &v);
+               gtk_hsv_set_color (hsv, priv->h, s, v);
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+/* Button_release_event handler for the HSV color selector */
+static gint
+gtk_hsv_button_release (GtkWidget *widget, GdkEventButton *event)
+{
+       GtkHSV *hsv;
+       HSVPrivate *priv;
+       DragMode mode;
+       double x, y;
+
+       hsv = GTK_HSV (widget);
+       priv = hsv->priv;
+
+       if (priv->mode == DRAG_NONE || event->button != 1)
+               return FALSE;
+
+       /* Set the drag mode to DRAG_NONE so that signal handlers for "catched"
+        * can see that this is the final color state.
+        */
+
+       mode = priv->mode;
+       priv->mode = DRAG_NONE;
+
+       x = event->x;
+       y = event->y;
+
+       if (mode == DRAG_H)
+               gtk_hsv_set_color (hsv, compute_v (hsv, x, y), priv->s, priv->v);
+       else if (mode == DRAG_SV) {
+               double s, v;
+
+               compute_sv (hsv, x, y, &s, &v);
+               gtk_hsv_set_color (hsv, priv->h, s, v);
+       } else
+               g_assert_not_reached ();
+
+       gdk_pointer_ungrab (event->time);
+
+       return TRUE;
+}
+
+/* Motion_notify_event handler for the HSV color selector */
+static gint
+gtk_hsv_motion (GtkWidget *widget, GdkEventMotion *event)
+{
+       GtkHSV *hsv;
+       HSVPrivate *priv;
+       double x, y;
+       gint ix, iy;
+       GdkModifierType mods;
+
+       hsv = GTK_HSV (widget);
+       priv = hsv->priv;
+
+       if (priv->mode == DRAG_NONE)
+               return FALSE;
+
+       if (event->is_hint) {
+               gdk_window_get_pointer (priv->window, &ix, &iy, &mods);
+               x = ix;
+               y = iy;
+       } else {
+               x = event->x;
+               y = event->y;
+       }
+
+       if (priv->mode == DRAG_H) {
+               gtk_hsv_set_color (hsv, compute_v (hsv, x, y), priv->s, priv->v);
+               return TRUE;
+       } else if (priv->mode == DRAG_SV) {
+               double s, v;
+
+               compute_sv (hsv, x, y, &s, &v);
+               gtk_hsv_set_color (hsv, priv->h, s, v);
+               return TRUE;
+       }
+
+       g_assert_not_reached ();
+       return FALSE;
+}
+
+\f
+
+/* Redrawing */
+
+/* Paints the hue ring */
+static void
+paint_ring (GtkHSV *hsv, GdkDrawable *drawable, int x, int y, int width, int height)
+{
+       HSVPrivate *priv;
+       int xx, yy;
+       double dx, dy, dist;
+       double center;
+       double inner, outer;
+       guchar *buf, *p;
+       double angle;
+       double hue;
+       double r, g, b;
+       GdkBitmap *mask;
+       GdkGC *gc;
+       GdkColor color;
+
+       priv = hsv->priv;
+
+       center = priv->size / 2.0;
+
+       outer = priv->size / 2.0;
+       inner = outer - priv->ring_width;
+
+       /* Paint the ring */
+
+       buf = g_new (guchar, width * height * 3);
+
+       for (yy = 0; yy < height; yy++) {
+               p = buf + yy * width * 3;
+
+               dy = -(yy + y - center);
+
+               for (xx = 0; xx < width; xx++) {
+                       dx = xx + x - center;
+
+                       dist = dx * dx + dy * dy;
+                       if (dist < (inner * inner) || dist > (outer * outer)) {
+                               *p++ = 0;
+                               *p++ = 0;
+                               *p++ = 0;
+                               continue;
+                       }
+
+                       angle = atan2 (dy, dx);
+                       if (angle < 0.0)
+                               angle += 2.0 * M_PI;
+
+                       hue = angle / (2.0 * M_PI);
+
+                       r = hue;
+                       g = 1.0;
+                       b = 1.0;
+                       hsv_to_rgb (&r, &g, &b);
+
+                       *p++ = floor (r * 255 + 0.5);
+                       *p++ = floor (g * 255 + 0.5);
+                       *p++ = floor (b * 255 + 0.5);
+               }
+       }
+
+       /* Create clipping mask */
+
+       mask = gdk_pixmap_new (NULL, width, height, 1);
+       gc = gdk_gc_new (mask);
+
+       color.pixel = 0;
+       gdk_gc_set_foreground (gc, &color);
+       gdk_draw_rectangle (mask, gc, TRUE,
+                           0, 0, width, height);
+
+
+       color.pixel = 1;
+       gdk_gc_set_foreground (gc, &color);
+       gdk_draw_arc (mask, gc, TRUE,
+                     -x, -y,
+                     priv->size - 1, priv->size - 1,
+                     0, 360 * 64);
+
+       color.pixel = 0;
+       gdk_gc_set_foreground (gc, &color);
+       gdk_draw_arc (mask, gc, TRUE,
+                     -x + priv->ring_width - 1, -y + priv->ring_width - 1,
+                     priv->size - 2 * priv->ring_width + 1, priv->size - 2 * priv->ring_width + 1,
+                     0, 360 * 64);
+
+       gdk_gc_unref (gc);
+
+       gdk_gc_set_clip_mask (priv->gc, mask);
+       gdk_gc_set_clip_origin (priv->gc, 0, 0);
+
+       /* Draw ring */
+
+       gdk_draw_rgb_image_dithalign (drawable, priv->gc, 0, 0, width, height,
+                                     GDK_RGB_DITHER_MAX,
+                                     buf,
+                                     width * 3,
+                                     x, y);
+
+       /* Draw value marker */
+
+       r = priv->h;
+       g = 1.0;
+       b = 1.0;
+       hsv_to_rgb (&r, &g, &b);
+
+       if (INTENSITY (r, g, b) > 0.5)
+               gdk_rgb_gc_set_foreground (priv->gc, 0x000000);
+       else
+               gdk_rgb_gc_set_foreground (priv->gc, 0xffffff);
+
+       gdk_draw_line (drawable, priv->gc,
+                      -x + center, -y + center,
+                      -x + center + cos (priv->h * 2.0 * M_PI) * center,
+                      -y + center - sin (priv->h * 2.0 * M_PI) * center);
+
+       gdk_gc_set_clip_mask (priv->gc, NULL);
+       gdk_bitmap_unref (mask);
+
+       g_free (buf);
+
+       /* Draw ring outline */
+
+       gdk_rgb_gc_set_foreground (priv->gc, 0x000000);
+
+       gdk_draw_arc (drawable, priv->gc, FALSE,
+                     -x, -y,
+                     priv->size - 1, priv->size - 1,
+                     0, 360 * 64);
+       gdk_draw_arc (drawable, priv->gc, FALSE,
+                     -x + priv->ring_width - 1, -y + priv->ring_width - 1,
+                     priv->size - 2 * priv->ring_width + 1, priv->size - 2 * priv->ring_width + 1,
+                     0, 360 * 64);
+}
+
+/* Converts an HSV triplet to an integer RGB triplet */
+static void
+get_color (double h, double s, double v, int *r, int *g, int *b)
+{
+       hsv_to_rgb (&h, &s, &v);
+
+       *r = floor (h * 255 + 0.5);
+       *g = floor (s * 255 + 0.5);
+       *b = floor (v * 255 + 0.5);
+}
+
+#define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
+
+#define LERP(a, b, v1, v2, i) (((v2) - (v1) != 0)                                      \
+                              ? ((a) + ((b) - (a)) * ((i) - (v1)) / ((v2) - (v1)))     \
+                              : (a))
+
+/* Paints the HSV triangle */
+static void
+paint_triangle (GtkHSV *hsv, GdkDrawable *drawable, int x, int y, int width, int height)
+{
+       HSVPrivate *priv;
+       int hx, hy, sx, sy, vx, vy; /* HSV vertices */
+       int x1, y1, r1, g1, b1; /* First vertex in scanline order */
+       int x2, y2, r2, g2, b2; /* Second vertex */
+       int x3, y3, r3, g3, b3; /* Third vertex */
+       int t;
+       guchar *buf, *p;
+       int xl, xr, rl, rr, gl, gr, bl, br; /* Scanline data */
+       int xx, yy;
+       GdkBitmap *mask;
+       GdkGC *gc;
+       GdkColor color;
+       GdkPoint points[3];
+       double r, g, b;
+
+       priv = hsv->priv;
+
+       /* Compute triangle's vertices */
+
+       compute_triangle (hsv, &hx, &hy, &sx, &sy, &vx, &vy);
+
+       x1 = hx;
+       y1 = hy;
+       get_color (priv->h, 1.0, 1.0, &r1, &g1, &b1);
+
+       x2 = sx;
+       y2 = sy;
+       get_color (priv->h, 1.0, 0.0, &r2, &g2, &b2);
+
+       x3 = vx;
+       y3 = vy;
+       get_color (priv->h, 0.0, 1.0, &r3, &g3, &b3);
+
+       if (y2 > y3) {
+               SWAP (x2, x3, t);
+               SWAP (y2, y3, t);
+               SWAP (r2, r3, t);
+               SWAP (g2, g3, t);
+               SWAP (b2, b3, t);
+       }
+
+       if (y1 > y3) {
+               SWAP (x1, x3, t);
+               SWAP (y1, y3, t);
+               SWAP (r1, r3, t);
+               SWAP (g1, g3, t);
+               SWAP (b1, b3, t);
+       }
+
+       if (y1 > y2) {
+               SWAP (x1, x2, t);
+               SWAP (y1, y2, t);
+               SWAP (r1, r2, t);
+               SWAP (g1, g2, t);
+               SWAP (b1, b2, t);
+       }
+
+       /* Shade the triangle */
+
+       buf = g_new (guchar, width * height * 3);
+
+       for (yy = 0; yy < height; yy++) {
+               p = buf + yy * width * 3;
+
+               if (yy + y < y1 || yy + y > y3)
+                       for (xx = 0; xx < width; xx++) {
+                               *p++ = 0;
+                               *p++ = 0;
+                               *p++ = 0;
+                       }
+               else {
+                       if (yy + y < y2) {
+                               xl = LERP (x1, x2, y1, y2, yy + y);
+
+                               rl = LERP (r1, r2, y1, y2, yy + y);
+                               gl = LERP (g1, g2, y1, y2, yy + y);
+                               bl = LERP (b1, b2, y1, y2, yy + y);
+                       } else {
+                               xl = LERP (x2, x3, y2, y3, yy + y);
+
+                               rl = LERP (r2, r3, y2, y3, yy + y);
+                               gl = LERP (g2, g3, y2, y3, yy + y);
+                               bl = LERP (b2, b3, y2, y3, yy + y);
+                       }
+
+                       xr = LERP (x1, x3, y1, y3, yy + y);
+
+                       rr = LERP (r1, r3, y1, y3, yy + y);
+                       gr = LERP (g1, g3, y1, y3, yy + y);
+                       br = LERP (b1, b3, y1, y3, yy + y);
+
+                       if (xl > xr) {
+                               SWAP (xl, xr, t);
+                               SWAP (rl, rr, t);
+                               SWAP (gl, gr, t);
+                               SWAP (bl, br, t);
+                       }
+
+                       for (xx = 0; xx < width; xx++) {
+                               if (xx + x < xl || xx + x > xr) {
+                                       *p++ = 0;
+                                       *p++ = 0;
+                                       *p++ = 0;
+                               } else {
+                                       *p++ = LERP (rl, rr, xl, xr, xx + x);
+                                       *p++ = LERP (gl, gr, xl, xr, xx + x);
+                                       *p++ = LERP (bl, br, xl, xr, xx + x);
+                               }
+                       }
+               }
+       }
+
+       /* Create clipping mask */
+
+       mask = gdk_pixmap_new (NULL, width, height, 1);
+       gc = gdk_gc_new (mask);
+
+       color.pixel = 0;
+       gdk_gc_set_foreground (gc, &color);
+       gdk_draw_rectangle (mask, gc, TRUE,
+                           0, 0, width, height);
+
+       color.pixel = 1;
+       gdk_gc_set_foreground (gc, &color);
+
+       points[0].x = x1 - x;
+       points[0].y = y1 - y;
+       points[1].x = x2 - x;
+       points[1].y = y2 - y;
+       points[2].x = x3 - x;
+       points[2].y = y3 - y;
+       gdk_draw_polygon (mask, gc, TRUE, points, 3);
+
+       gdk_gc_unref (gc);
+
+       gdk_gc_set_clip_mask (priv->gc, mask);
+       gdk_gc_set_clip_origin (priv->gc, 0, 0);
+
+       /* Draw triangle */
+
+       gdk_draw_rgb_image_dithalign (drawable, priv->gc, 0, 0, width, height,
+                                     GDK_RGB_DITHER_MAX,
+                                     buf,
+                                     width * 3,
+                                     x, y);
+
+       gdk_gc_set_clip_mask (priv->gc, NULL);
+       gdk_bitmap_unref (mask);
+
+       g_free (buf);
+
+       /* Draw triangle outline */
+
+       gdk_rgb_gc_set_foreground (priv->gc, 0x000000);
+
+       gdk_draw_polygon (drawable, priv->gc, FALSE, points, 3);
+
+       /* Draw value marker */
+
+       xx = floor (sx + (vx - sx) * priv->v + (hx - vx) * priv->s * priv->v + 0.5);
+       yy = floor (sy + (vy - sy) * priv->v + (hy - vy) * priv->s * priv->v + 0.5);
+
+       r = priv->h;
+       g = priv->s;
+       b = priv->v;
+       hsv_to_rgb (&r, &g, &b);
+
+       if (INTENSITY (r, g, b) > 0.5)
+               gdk_rgb_gc_set_foreground (priv->gc, 0x000000);
+       else
+               gdk_rgb_gc_set_foreground (priv->gc, 0xffffff);
+
+       gdk_draw_arc (drawable, priv->gc, FALSE,
+                     xx - 3, yy - 3,
+                     6, 6,
+                     0, 360 * 64);
+       gdk_draw_arc (drawable, priv->gc, FALSE,
+                     xx - 2, yy - 2,
+                     4, 4,
+                     0, 360 * 64);
+}
+
+/* Paints the contents of the HSV color selector */
+static void
+paint (GtkHSV *hsv, GdkDrawable *drawable, int x, int y, int width, int height)
+{
+       paint_ring (hsv, drawable, x, y, width, height);
+       paint_triangle (hsv, drawable, x, y, width, height);
+}
+
+/* Expose_event handler for the HSV color selector */
+static gint
+gtk_hsv_expose (GtkWidget *widget, GdkEventExpose *event)
+{
+       GtkHSV *hsv;
+       HSVPrivate *priv;
+       GdkRectangle rect, dest;
+       GdkPixmap *pixmap;
+
+       hsv = GTK_HSV (widget);
+       priv = hsv->priv;
+
+       if (!(GTK_WIDGET_DRAWABLE (widget) && event->window == widget->window))
+               return FALSE;
+
+       rect.x = widget->allocation.x;
+       rect.y = widget->allocation.y;
+       rect.width = widget->allocation.width;
+       rect.height = widget->allocation.height;
+
+       if (!gdk_rectangle_intersect (&event->area, &rect, &dest))
+               return FALSE;
+
+       pixmap = gdk_pixmap_new (widget->window, dest.width, dest.height,
+                                gtk_widget_get_visual (widget)->depth);
+
+       rect = dest;
+       rect.x = 0;
+       rect.y = 0;
+
+       gdk_draw_rectangle (pixmap,
+                           widget->style->bg_gc[GTK_WIDGET_STATE (widget)],
+                           TRUE,
+                           0, 0, dest.width, dest.height);
+       paint (hsv, pixmap,
+              dest.x - widget->allocation.x, dest.y - widget->allocation.y,
+              dest.width, dest.height);
+
+       gdk_draw_pixmap (widget->window,
+                        priv->gc,
+                        pixmap,
+                        0, 0,
+                        dest.x,
+                        dest.y,
+                        event->area.width, event->area.height);
+
+       gdk_pixmap_unref (pixmap);
+
+       return FALSE;
+}
+
+\f
+
+/**
+ * gtk_hsv_new:
+ * @void:
+ *
+ * Creates a new HSV color selector.
+ *
+ * Return value: A newly-created HSV color selector.
+ **/
+GtkWidget *
+gtk_hsv_new (void)
+{
+       return GTK_WIDGET (gtk_type_new (gtk_hsv_get_type ()));
+}
+
+/**
+ * gtk_hsv_set_color:
+ * @hsv: An HSV color selector.
+ * @h: Hue.
+ * @s: Saturation.
+ * @v: Value.
+ *
+ * Sets the current color in an HSV color selector.  Color component values must
+ * be in the [0.0, 1.0] range.
+ **/
+void
+gtk_hsv_set_color (GtkHSV *hsv, double h, double s, double v)
+{
+       HSVPrivate *priv;
+
+       g_return_if_fail (hsv != NULL);
+       g_return_if_fail (GTK_IS_HSV (hsv));
+       g_return_if_fail (h >= 0.0 && h <= 1.0);
+       g_return_if_fail (s >= 0.0 && s <= 1.0);
+       g_return_if_fail (v >= 0.0 && v <= 1.0);
+
+       priv = hsv->priv;
+
+       priv->h = h;
+       priv->s = s;
+       priv->v = v;
+
+       gtk_signal_emit (GTK_OBJECT (hsv), hsv_signals[CHANGED]);
+
+       gtk_widget_queue_draw (GTK_WIDGET (hsv));
+}
+
+/**
+ * gtk_hsv_get_color:
+ * @hsv: An HSV color selector.
+ * @h: Return value for the hue.
+ * @s: Return value for the saturation.
+ * @v: Return value for the value.
+ *
+ * Queries the current color in an HSV color selector.  Returned values will be
+ * in the [0.0, 1.0] range.
+ **/
+void
+gtk_hsv_get_color (GtkHSV *hsv, double *h, double *s, double *v)
+{
+       HSVPrivate *priv;
+
+       g_return_if_fail (hsv != NULL);
+       g_return_if_fail (GTK_IS_HSV (hsv));
+
+       priv = hsv->priv;
+
+       if (h)
+               *h = priv->h;
+
+       if (s)
+               *s = priv->s;
+
+       if (v)
+               *v = priv->v;
+}
+
+/**
+ * gtk_hsv_set_metrics:
+ * @hsv: An HSV color selector.
+ * @size: Diameter for the hue ring.
+ * @ring_width: Width of the hue ring.
+ *
+ * Sets the size and ring width of an HSV color selector.
+ **/
+void
+gtk_hsv_set_metrics (GtkHSV *hsv, int size, int ring_width)
+{
+       HSVPrivate *priv;
+       int same_size;
+
+       g_return_if_fail (hsv != NULL);
+       g_return_if_fail (GTK_IS_HSV (hsv));
+       g_return_if_fail (size > 0);
+       g_return_if_fail (ring_width > 0);
+       g_return_if_fail (2 * ring_width + 1 <= size);
+
+       priv = hsv->priv;
+
+       same_size = (priv->size == size);
+
+       priv->size = size;
+       priv->ring_width = ring_width;
+
+       if (same_size)
+               gtk_widget_queue_draw (GTK_WIDGET (hsv));
+       else
+               gtk_widget_queue_resize (GTK_WIDGET (hsv));
+}
+
+/**
+ * gtk_hsv_get_metrics:
+ * @hsv: An HSV color selector.
+ * @size: Return value for the diameter of the hue ring.
+ * @ring_width: Return value for the width of the hue ring.
+ *
+ * Queries the size and ring width of an HSV color selector.
+ **/
+void
+gtk_hsv_get_metrics (GtkHSV *hsv, int *size, int *ring_width)
+{
+       HSVPrivate *priv;
+
+       g_return_if_fail (hsv != NULL);
+       g_return_if_fail (GTK_IS_HSV (hsv));
+
+       priv = hsv->priv;
+
+       if (size)
+               *size = priv->size;
+
+       if (ring_width)
+               *ring_width = priv->ring_width;
+}
+
+/**
+ * gtk_hsv_is_adjusting:
+ * @hsv:
+ *
+ * An HSV color selector can be said to be adjusting if multiple rapid changes
+ * are being made to its value, for example, when the user is adjusting the
+ * value with the mouse.  This function queries whether the HSV color selector
+ * is being adjusted or not.
+ *
+ * Return value: TRUE if clients can ignore changes to the color value, since
+ * they may be transitory, or FALSE if they should consider the color value
+ * status to be final.
+ **/
+gboolean
+gtk_hsv_is_adjusting (GtkHSV *hsv)
+{
+       HSVPrivate *priv;
+
+       g_return_val_if_fail (hsv != NULL, FALSE);
+       g_return_val_if_fail (GTK_IS_HSV (hsv), FALSE);
+
+       priv = hsv->priv;
+       return (priv->mode != DRAG_NONE);
+}
+
+/**
+ * gtk_hsv_to_rgb:
+ * @h: Hue.
+ * @s: Saturation.
+ * @v: Value.
+ * @r: Return value for the red component.
+ * @g: Return value for the green component.
+ * @b: Return value for the blue component.
+ * 
+ * Converts a color from HSV space to RGB.  Input values must be in the
+ * [0.0, 1.0] range; output values will be in the same range.
+ **/
+void
+gtk_hsv_to_rgb (double h, double s, double v, double *r, double *g, double *b)
+{
+       g_return_if_fail (h >= 0.0 && h <= 1.0);
+       g_return_if_fail (s >= 0.0 && s <= 1.0);
+       g_return_if_fail (v >= 0.0 && v <= 1.0);
+
+       hsv_to_rgb (&h, &s, &v);
+
+       if (r)
+               *r = h;
+
+       if (g)
+               *g = s;
+
+       if (b)
+               *b = v;
+}
+
+/**
+ * gtk_hsv_to_rgb:
+ * @r: Red.
+ * @g: Green.
+ * @b: Blue.
+ * @h: Return value for the hue component.
+ * @s: Return value for the saturation component.
+ * @v: Return value for the value component.
+ * 
+ * Converts a color from RGB space to HSV.  Input values must be in the
+ * [0.0, 1.0] range; output values will be in the same range.
+ **/
+void
+gtk_rgb_to_hsv (double r, double g, double b, double *h, double *s, double *v)
+{
+       g_return_if_fail (r >= 0.0 && r <= 1.0);
+       g_return_if_fail (g >= 0.0 && g <= 1.0);
+       g_return_if_fail (b >= 0.0 && b <= 1.0);
+
+       rgb_to_hsv (&r, &g, &b);
+
+       if (h)
+               *h = r;
+
+       if (s)
+               *s = g;
+
+       if (v)
+               *v = b;
+}
diff --git a/gtk/gtkhsv.h b/gtk/gtkhsv.h
new file mode 100644 (file)
index 0000000..ffe6ff7
--- /dev/null
@@ -0,0 +1,83 @@
+/* HSV color selector for GTK+
+ *
+ * Copyright (C) 1999 The Free Software Foundation
+ *
+ * Authors: Simon Budig <Simon.Budig@unix-ag.org> (original code)
+ *          Federico Mena-Quintero <federico@gimp.org> (cleanup for GTK+)
+ *          Jonathan Blandford <jrb@redhat.com> (cleanup for GTK+)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_HSV_H__
+#define __GTK_HSV_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <gtk/gtkwidget.h>
+
+\f
+
+#define GTK_TYPE_HSV            (gtk_hsv_get_type ())
+#define GTK_HSV(obj)            (GTK_CHECK_CAST ((obj), GTK_TYPE_HSV, GtkHSV))
+#define GTK_HSV_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_HSV, GtkHSV))
+#define GTK_IS_HSV(obj)         (GTK_CHECK_TYPE ((obj), GTK_TYPE_HSV))
+#define GTK_IS_HSV_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_HSV))
+
+
+typedef struct _GtkHSV GtkHSV;
+typedef struct _GtkHSVClass GtkHSVClass;
+
+struct _GtkHSV {
+       GtkWidget widget;
+
+       /* Private data */
+       gpointer priv;
+};
+
+struct _GtkHSVClass {
+       GtkWidgetClass parent_class;
+
+       /* Notification signals */
+
+       void (* changed) (GtkHSV *hsv);
+};
+
+
+GtkType gtk_hsv_get_type (void);
+
+GtkWidget *gtk_hsv_new (void);
+
+void gtk_hsv_set_color (GtkHSV *hsv, double h, double s, double v);
+void gtk_hsv_get_color (GtkHSV *hsv, double *h, double *s, double *v);
+
+void gtk_hsv_set_metrics (GtkHSV *hsv, int size, int ring_width);
+void gtk_hsv_get_metrics (GtkHSV *hsv, int *size, int *ring_width);
+
+gboolean gtk_hsv_is_adjusting (GtkHSV *hsv);
+
+void gtk_hsv_to_rgb (double h, double s, double v, double *r, double *g, double *b);
+void gtk_rgb_to_hsv (double r, double g, double b, double *h, double *s, double *v);
+
+\f
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
index df1b4940dea35c44a2ca9a2700ca919f22ca9d8c..7a431e9d95a09e926ca33ef393feb9d5f3d0ec5a 100644 (file)
@@ -5179,6 +5179,28 @@ color_selection_changed (GtkWidget *w,
   gtk_color_selection_get_color(colorsel,color);
 }
 
+static void
+opacity_toggled_cb (GtkWidget *w,
+                   GtkColorSelectionDialog *cs)
+{
+  GtkColorSelection *colorsel;
+
+  colorsel = GTK_COLOR_SELECTION (cs->colorsel);
+  gtk_color_selection_set_use_opacity (colorsel,
+                                      gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
+}
+
+static void
+palette_toggled_cb (GtkWidget *w,
+                   GtkColorSelectionDialog *cs)
+{
+  GtkColorSelection *colorsel;
+
+  colorsel = GTK_COLOR_SELECTION (cs->colorsel);
+  gtk_color_selection_set_use_palette (colorsel,
+                                      gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
+}
+
 void
 create_color_selection (void)
 {
@@ -5186,22 +5208,37 @@ create_color_selection (void)
 
   if (!window)
     {
+      GtkWidget *options_hbox;
+      GtkWidget *check_button;
+      
       window = gtk_color_selection_dialog_new ("color selection dialog");
 
-      gtk_color_selection_set_opacity (
+      gtk_color_selection_set_use_opacity (
         GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (window)->colorsel),
        TRUE);
 
-      gtk_color_selection_set_update_policy(
-        GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (window)->colorsel),
-       GTK_UPDATE_CONTINUOUS);
-
       gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
 
       gtk_signal_connect (GTK_OBJECT (window), "destroy",
                           GTK_SIGNAL_FUNC(gtk_widget_destroyed),
                           &window);
 
+      options_hbox = gtk_hbox_new (FALSE, 0);
+      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), options_hbox, FALSE, FALSE, 0);
+      gtk_container_set_border_width (GTK_CONTAINER (options_hbox), 10);
+      
+      check_button = gtk_check_button_new_with_label ("Show Opacity");
+      gtk_box_pack_start (GTK_BOX (options_hbox), check_button, FALSE, FALSE, 0);
+      gtk_signal_connect (GTK_OBJECT (check_button), "toggled",
+                         GTK_SIGNAL_FUNC (opacity_toggled_cb), window);
+
+      check_button = gtk_check_button_new_with_label ("Show Palette");
+      gtk_box_pack_end (GTK_BOX (options_hbox), check_button, FALSE, FALSE, 0);
+      gtk_signal_connect (GTK_OBJECT (check_button), "toggled",
+                         GTK_SIGNAL_FUNC (palette_toggled_cb), window);
+
+      gtk_widget_show_all (options_hbox);
+
       gtk_signal_connect (
        GTK_OBJECT (GTK_COLOR_SELECTION_DIALOG (window)->colorsel),
        "color_changed",
index df1b4940dea35c44a2ca9a2700ca919f22ca9d8c..7a431e9d95a09e926ca33ef393feb9d5f3d0ec5a 100644 (file)
@@ -5179,6 +5179,28 @@ color_selection_changed (GtkWidget *w,
   gtk_color_selection_get_color(colorsel,color);
 }
 
+static void
+opacity_toggled_cb (GtkWidget *w,
+                   GtkColorSelectionDialog *cs)
+{
+  GtkColorSelection *colorsel;
+
+  colorsel = GTK_COLOR_SELECTION (cs->colorsel);
+  gtk_color_selection_set_use_opacity (colorsel,
+                                      gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
+}
+
+static void
+palette_toggled_cb (GtkWidget *w,
+                   GtkColorSelectionDialog *cs)
+{
+  GtkColorSelection *colorsel;
+
+  colorsel = GTK_COLOR_SELECTION (cs->colorsel);
+  gtk_color_selection_set_use_palette (colorsel,
+                                      gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
+}
+
 void
 create_color_selection (void)
 {
@@ -5186,22 +5208,37 @@ create_color_selection (void)
 
   if (!window)
     {
+      GtkWidget *options_hbox;
+      GtkWidget *check_button;
+      
       window = gtk_color_selection_dialog_new ("color selection dialog");
 
-      gtk_color_selection_set_opacity (
+      gtk_color_selection_set_use_opacity (
         GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (window)->colorsel),
        TRUE);
 
-      gtk_color_selection_set_update_policy(
-        GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (window)->colorsel),
-       GTK_UPDATE_CONTINUOUS);
-
       gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
 
       gtk_signal_connect (GTK_OBJECT (window), "destroy",
                           GTK_SIGNAL_FUNC(gtk_widget_destroyed),
                           &window);
 
+      options_hbox = gtk_hbox_new (FALSE, 0);
+      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), options_hbox, FALSE, FALSE, 0);
+      gtk_container_set_border_width (GTK_CONTAINER (options_hbox), 10);
+      
+      check_button = gtk_check_button_new_with_label ("Show Opacity");
+      gtk_box_pack_start (GTK_BOX (options_hbox), check_button, FALSE, FALSE, 0);
+      gtk_signal_connect (GTK_OBJECT (check_button), "toggled",
+                         GTK_SIGNAL_FUNC (opacity_toggled_cb), window);
+
+      check_button = gtk_check_button_new_with_label ("Show Palette");
+      gtk_box_pack_end (GTK_BOX (options_hbox), check_button, FALSE, FALSE, 0);
+      gtk_signal_connect (GTK_OBJECT (check_button), "toggled",
+                         GTK_SIGNAL_FUNC (palette_toggled_cb), window);
+
+      gtk_widget_show_all (options_hbox);
+
       gtk_signal_connect (
        GTK_OBJECT (GTK_COLOR_SELECTION_DIALOG (window)->colorsel),
        "color_changed",